Browse Source

Updated compressed instructions for RV32D

Eyck Jentzsch 1 year ago
parent
commit
65ceedd157
3 changed files with 263 additions and 55 deletions
  1. 37
    7
      riscv/gen_input/RV32C.core_desc
  2. 1
    1
      riscv/gen_input/minres_rv.core_desc
  3. 225
    47
      riscv/src/internal/vm_rv32gc.cpp

+ 37
- 7
riscv/gen_input/RV32C.core_desc View File

@@ -218,9 +218,9 @@ InsructionSet RV32FC extends RV32IC{
218 218
 			val res[32] <= MEM[offs]{32};
219 219
 			if(FLEN==32)
220 220
 				F[rd_idx] <= res;
221
-			else {
222
-				val upper[FLEN] <= (-1<<31);
223
-				F[rd_idx] <= upper*2 | res;
221
+			else { // NaN boxing
222
+				val upper[FLEN] <= -1;
223
+				F[rd] <= (upper<<32) | zext(res, FLEN);
224 224
 			}
225 225
 		} 
226 226
 		C.FSW {
@@ -239,9 +239,9 @@ InsructionSet RV32FC extends RV32IC{
239 239
 			val res[32] <= MEM[offs]{32};
240 240
 			if(FLEN==32)
241 241
 				F[rd] <= res;
242
-			else {
243
-				val upper[FLEN] <= (-1<<31);
244
-				F[rd] <= upper*2 | res;
242
+			else { // NaN boxing
243
+				val upper[FLEN] <= -1;
244
+				F[rd] <= (upper<<32) | zext(res, FLEN);
245 245
 			}
246 246
 		}
247 247
 		C.FSWSP {
@@ -249,7 +249,7 @@ InsructionSet RV32FC extends RV32IC{
249 249
 			args_disass:"f%rs2$d, %uimm%(x2), ";
250 250
 			val x2_idx[5] <= 2;
251 251
 			val offs[XLEN] <= X[x2_idx]+uimm;
252
-			MEM[offs]{32}<=F[rs2];
252
+			MEM[offs]{32}<=F[rs2]{32};
253 253
 		}		
254 254
 	}
255 255
 }
@@ -268,15 +268,45 @@ InsructionSet RV32DC extends RV32IC{
268 268
 	instructions{
269 269
 		C.FLD { //(RV32/64)
270 270
 			encoding: b001 | uimm[5:3] | rs1[2:0] | uimm[7:6] | rd[2:0] | b00;
271
+			args_disass:"f(8+%rd$d), %uimm%(x(8+%rs1$d))";
272
+			val rs1_idx[5] <= rs1+8;
273
+			val rd_idx[5] <= rd+8;
274
+			val offs[XLEN] <= X[rs1_idx]+uimm;
275
+			val res[64] <= MEM[offs]{64};
276
+			if(FLEN==64)
277
+				F[rd_idx] <= res;
278
+			else { // NaN boxing
279
+				val upper[FLEN] <= -1;
280
+				F[rd_idx] <= (upper<<64) | res;
281
+			}
271 282
 	 	}
272 283
 		C.FSD { //(RV32/64)
273 284
 			encoding: b101 | uimm[5:3] | rs1[2:0] | uimm[7:6] | rs2[2:0] | b00;
285
+			args_disass:"f(8+%rs2$d), %uimm%(x(8+%rs1$d))";
286
+			val rs1_idx[5] <= rs1+8;
287
+			val rs2_idx[5] <= rs2+8;
288
+			val offs[XLEN] <= X[rs1_idx]+uimm;
289
+			MEM[offs]{64}<=F[rs2_idx]{64};
274 290
 		} 
275 291
 		C.FLDSP {//(RV32/64)
276 292
 			encoding:b001 | uimm[5:5] | rd[4:0] | uimm[4:3] | uimm[8:6] | b10;
293
+			args_disass:"f%rd$d, %uimm%(x2)";
294
+			val x2_idx[5] <= 2;
295
+			val offs[XLEN] <= X[x2_idx]+uimm;
296
+			val res[64] <= MEM[offs]{64};
297
+			if(FLEN==64)
298
+				F[rd] <= res;
299
+			else { // NaN boxing
300
+				val upper[FLEN] <= -1;
301
+				F[rd] <= (upper<<64) | zext(res, FLEN);
302
+			}
277 303
 		}
278 304
 		C.FSDSP {//(RV32/64)
279 305
 			encoding:b101 | uimm[5:3] | uimm[8:6] | rs2[4:0] | b10;
306
+			args_disass:"f%rs2$d, %uimm%(x2), ";
307
+			val x2_idx[5] <= 2;
308
+			val offs[XLEN] <= X[x2_idx]+uimm;
309
+			MEM[offs]{64}<=F[rs2]{64};
280 310
 		}
281 311
 	}
282 312
 }

+ 1
- 1
riscv/gen_input/minres_rv.core_desc View File

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

+ 225
- 47
riscv/src/internal/vm_rv32gc.cpp View File

@@ -194,7 +194,7 @@ private:
194 194
         compile_func op;
195 195
     };
196 196
 
197
-    const std::array<InstructionDesriptor, 155> instr_descr = {{
197
+    const std::array<InstructionDesriptor, 159> instr_descr = {{
198 198
          /* entries are: size, valid value, valid mask, function ptr */
199 199
         /* instruction LUI */
200 200
         {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui},
@@ -506,6 +506,14 @@ private:
506 506
         {32, 0b11010010000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_d_w},
507 507
         /* instruction FCVT.D.WU */
508 508
         {32, 0b11010010000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_d_wu},
509
+        /* instruction C.FLD */
510
+        {16, 0b0010000000000000, 0b1110000000000011, &this_class::__c_fld},
511
+        /* instruction C.FSD */
512
+        {16, 0b1010000000000000, 0b1110000000000011, &this_class::__c_fsd},
513
+        /* instruction C.FLDSP */
514
+        {16, 0b0010000000000010, 0b1110000000000011, &this_class::__c_fldsp},
515
+        /* instruction C.FSDSP */
516
+        {16, 0b1010000000000010, 0b1110000000000011, &this_class::__c_fsdsp},
509 517
     }};
510 518
  
511 519
     /* instruction definitions */
@@ -641,43 +649,19 @@ private:
641 649
     	Value* cur_pc_val = this->gen_const(32, pc.val);
642 650
     	pc=pc+4;
643 651
     	
644
-    	Value* new_pc_val = this->builder.CreateAdd(
652
+    	if(fld_rd_val != 0){
653
+    	    Value* X_rd_val = this->builder.CreateAdd(
654
+    	        cur_pc_val,
655
+    	        this->gen_const(32U, 4));
656
+    	    this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits<ARCH>::X0), false);
657
+    	}
658
+    	Value* ret_val = this->builder.CreateAdd(
645 659
     	    this->gen_reg_load(fld_rs1_val + traits<ARCH>::X0, 0),
646 660
     	    this->gen_const(32U, fld_imm_val));
647
-    	Value* align_val = this->builder.CreateAnd(
648
-    	    new_pc_val,
649
-    	    this->gen_const(32U, 2));
650
-    	llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk);
651
-    	llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext);
652
-    	llvm::BasicBlock* bb_else = llvm::BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext);
653
-    	// this->builder.SetInsertPoint(bb);
654
-    	this->gen_cond_branch(this->builder.CreateICmp(
655
-    	    ICmpInst::ICMP_NE,
656
-    	    align_val,
657
-    	    this->gen_const(32U, 0)),
658
-    	    bb_then,
659
-    	    bb_else);
660
-    	this->builder.SetInsertPoint(bb_then);
661
-    	{
662
-    	    this->gen_raise_trap(0, 0);
663
-    	}
664
-    	this->builder.CreateBr(bbnext);
665
-    	this->builder.SetInsertPoint(bb_else);
666
-    	{
667
-    	    if(fld_rd_val != 0){
668
-    	        Value* X_rd_val = this->builder.CreateAdd(
669
-    	            cur_pc_val,
670
-    	            this->gen_const(32U, 4));
671
-    	        this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits<ARCH>::X0), false);
672
-    	    }
673
-    	    Value* PC_val = this->builder.CreateAnd(
674
-    	        new_pc_val,
675
-    	        this->builder.CreateNot(this->gen_const(32U, 1)));
676
-    	    this->builder.CreateStore(PC_val, get_reg_ptr(traits<ARCH>::NEXT_PC), false);
677
-    	}
678
-    	this->builder.CreateBr(bbnext);
679
-    	bb=bbnext;
680
-    	this->builder.SetInsertPoint(bb);
661
+    	Value* PC_val = this->builder.CreateAnd(
662
+    	    ret_val,
663
+    	    this->builder.CreateNot(this->gen_const(32U, 1)));
664
+    	this->builder.CreateStore(PC_val, get_reg_ptr(traits<ARCH>::NEXT_PC), false);
681 665
     	this->gen_sync(iss::POST_SYNC, 3);
682 666
     	this->gen_trap_check(this->leave_blk);
683 667
     	return std::make_tuple(iss::vm::BRANCH, nullptr);
@@ -6368,13 +6352,16 @@ private:
6368 6352
     	    Value* F_rd_idx_val = res_val;
6369 6353
     	    this->builder.CreateStore(F_rd_idx_val, get_reg_ptr(rd_idx_val + traits<ARCH>::F0), false);
6370 6354
     	} else {
6371
-    	    uint64_t upper_val = (-1) << 31;
6372
-    	    Value* F_rd_idx_val = this->builder.CreateOr(
6373
-    	        this->builder.CreateMul(
6355
+    	    uint64_t upper_val = (-1);
6356
+    	    Value* F_rd_val = this->builder.CreateOr(
6357
+    	        this->builder.CreateShl(
6374 6358
     	            this->gen_const(64U, upper_val),
6375
-    	            this->gen_const(64U, 2)),
6376
-    	        res_val);
6377
-    	    this->builder.CreateStore(F_rd_idx_val, get_reg_ptr(rd_idx_val + traits<ARCH>::F0), false);
6359
+    	            this->gen_const(64U, 32)),
6360
+    	        this->gen_ext(
6361
+    	            res_val,
6362
+    	            64,
6363
+    	            false));
6364
+    	    this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits<ARCH>::F0), false);
6378 6365
     	}
6379 6366
     	this->gen_set_pc(pc, traits<ARCH>::NEXT_PC);
6380 6367
     	this->gen_sync(iss::POST_SYNC, 125);
@@ -6459,12 +6446,15 @@ private:
6459 6446
     	    Value* F_rd_val = res_val;
6460 6447
     	    this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits<ARCH>::F0), false);
6461 6448
     	} else {
6462
-    	    uint64_t upper_val = (-1) << 31;
6449
+    	    uint64_t upper_val = (-1);
6463 6450
     	    Value* F_rd_val = this->builder.CreateOr(
6464
-    	        this->builder.CreateMul(
6451
+    	        this->builder.CreateShl(
6465 6452
     	            this->gen_const(64U, upper_val),
6466
-    	            this->gen_const(64U, 2)),
6467
-    	        res_val);
6453
+    	            this->gen_const(64U, 32)),
6454
+    	        this->gen_ext(
6455
+    	            res_val,
6456
+    	            64,
6457
+    	            false));
6468 6458
     	    this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits<ARCH>::F0), false);
6469 6459
     	}
6470 6460
     	this->gen_set_pc(pc, traits<ARCH>::NEXT_PC);
@@ -6501,7 +6491,10 @@ private:
6501 6491
     	Value* offs_val = this->builder.CreateAdd(
6502 6492
     	    this->gen_reg_load(x2_idx_val + traits<ARCH>::X0, 0),
6503 6493
     	    this->gen_const(32U, fld_uimm_val));
6504
-    	Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val + traits<ARCH>::F0, 0);
6494
+    	Value* MEM_offs_val = this->builder.CreateTrunc(
6495
+    	    this->gen_reg_load(fld_rs2_val + traits<ARCH>::F0, 0),
6496
+    	    this-> get_type(32) 
6497
+    	);
6505 6498
     	this->gen_write_mem(
6506 6499
     	    traits<ARCH>::MEM,
6507 6500
     	    offs_val,
@@ -8096,6 +8089,191 @@ private:
8096 8089
     	return std::make_tuple(vm::CONT, bb);
8097 8090
     }
8098 8091
     
8092
+    /* instruction 155: C.FLD */
8093
+    std::tuple<vm::continuation_e, llvm::BasicBlock*> __c_fld(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){
8094
+    	bb->setName("C.FLD");
8095
+    	
8096
+    	this->gen_sync(iss::PRE_SYNC, 155);
8097
+    	
8098
+    	uint8_t fld_rd_val = 0 | (bit_sub<2,3>(instr));
8099
+    	uint8_t fld_uimm_val = 0 | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,3>(instr) << 3);
8100
+    	uint8_t fld_rs1_val = 0 | (bit_sub<7,3>(instr));
8101
+    	if(this->disass_enabled){
8102
+    	    /* generate console output when executing the command */
8103
+    	    boost::format ins_fmter("C.FLD f(8+%1$d), %2%(x(8+%3$d))");
8104
+    	    ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_uimm_val % (uint64_t)fld_rs1_val;
8105
+    	    std::vector<llvm::Value*> args {
8106
+    	        this->core_ptr,
8107
+    	        this->gen_const(64, pc.val),
8108
+    	        this->builder.CreateGlobalStringPtr(ins_fmter.str()),
8109
+    	    };
8110
+    	    this->builder.CreateCall(this->mod->getFunction("print_disass"), args);
8111
+    	}
8112
+    	
8113
+    	Value* cur_pc_val = this->gen_const(32, pc.val);
8114
+    	pc=pc+2;
8115
+    	
8116
+    	uint8_t rs1_idx_val = (fld_rs1_val + 8);
8117
+    	uint8_t rd_idx_val = (fld_rd_val + 8);
8118
+    	Value* offs_val = this->builder.CreateAdd(
8119
+    	    this->gen_reg_load(rs1_idx_val + traits<ARCH>::X0, 0),
8120
+    	    this->gen_const(32U, fld_uimm_val));
8121
+    	Value* res_val = this->gen_read_mem(traits<ARCH>::MEM, offs_val, 64/8);
8122
+    	if(64 == 64){
8123
+    	    Value* F_rd_idx_val = res_val;
8124
+    	    this->builder.CreateStore(F_rd_idx_val, get_reg_ptr(rd_idx_val + traits<ARCH>::F0), false);
8125
+    	} else {
8126
+    	    uint64_t upper_val = (-1);
8127
+    	    Value* F_rd_idx_val = this->builder.CreateOr(
8128
+    	        this->builder.CreateShl(
8129
+    	            this->gen_const(64U, upper_val),
8130
+    	            this->gen_const(64U, 64)),
8131
+    	        res_val);
8132
+    	    this->builder.CreateStore(F_rd_idx_val, get_reg_ptr(rd_idx_val + traits<ARCH>::F0), false);
8133
+    	}
8134
+    	this->gen_set_pc(pc, traits<ARCH>::NEXT_PC);
8135
+    	this->gen_sync(iss::POST_SYNC, 155);
8136
+    	bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */
8137
+    	this->gen_trap_check(bb);
8138
+    	return std::make_tuple(vm::CONT, bb);
8139
+    }
8140
+    
8141
+    /* instruction 156: C.FSD */
8142
+    std::tuple<vm::continuation_e, llvm::BasicBlock*> __c_fsd(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){
8143
+    	bb->setName("C.FSD");
8144
+    	
8145
+    	this->gen_sync(iss::PRE_SYNC, 156);
8146
+    	
8147
+    	uint8_t fld_rs2_val = 0 | (bit_sub<2,3>(instr));
8148
+    	uint8_t fld_uimm_val = 0 | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,3>(instr) << 3);
8149
+    	uint8_t fld_rs1_val = 0 | (bit_sub<7,3>(instr));
8150
+    	if(this->disass_enabled){
8151
+    	    /* generate console output when executing the command */
8152
+    	    boost::format ins_fmter("C.FSD f(8+%1$d), %2%(x(8+%3$d))");
8153
+    	    ins_fmter % (uint64_t)fld_rs2_val % (uint64_t)fld_uimm_val % (uint64_t)fld_rs1_val;
8154
+    	    std::vector<llvm::Value*> args {
8155
+    	        this->core_ptr,
8156
+    	        this->gen_const(64, pc.val),
8157
+    	        this->builder.CreateGlobalStringPtr(ins_fmter.str()),
8158
+    	    };
8159
+    	    this->builder.CreateCall(this->mod->getFunction("print_disass"), args);
8160
+    	}
8161
+    	
8162
+    	Value* cur_pc_val = this->gen_const(32, pc.val);
8163
+    	pc=pc+2;
8164
+    	
8165
+    	uint8_t rs1_idx_val = (fld_rs1_val + 8);
8166
+    	uint8_t rs2_idx_val = (fld_rs2_val + 8);
8167
+    	Value* offs_val = this->builder.CreateAdd(
8168
+    	    this->gen_reg_load(rs1_idx_val + traits<ARCH>::X0, 0),
8169
+    	    this->gen_const(32U, fld_uimm_val));
8170
+    	Value* MEM_offs_val = this->builder.CreateTrunc(
8171
+    	    this->gen_reg_load(rs2_idx_val + traits<ARCH>::F0, 0),
8172
+    	    this-> get_type(64) 
8173
+    	);
8174
+    	this->gen_write_mem(
8175
+    	    traits<ARCH>::MEM,
8176
+    	    offs_val,
8177
+    	    this->builder.CreateZExtOrTrunc(MEM_offs_val,this->get_type(64)));
8178
+    	this->gen_set_pc(pc, traits<ARCH>::NEXT_PC);
8179
+    	this->gen_sync(iss::POST_SYNC, 156);
8180
+    	bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */
8181
+    	this->gen_trap_check(bb);
8182
+    	return std::make_tuple(vm::CONT, bb);
8183
+    }
8184
+    
8185
+    /* instruction 157: C.FLDSP */
8186
+    std::tuple<vm::continuation_e, llvm::BasicBlock*> __c_fldsp(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){
8187
+    	bb->setName("C.FLDSP");
8188
+    	
8189
+    	this->gen_sync(iss::PRE_SYNC, 157);
8190
+    	
8191
+    	uint16_t fld_uimm_val = 0 | (bit_sub<2,3>(instr) << 6) | (bit_sub<5,2>(instr) << 3) | (bit_sub<12,1>(instr) << 5);
8192
+    	uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr));
8193
+    	if(this->disass_enabled){
8194
+    	    /* generate console output when executing the command */
8195
+    	    boost::format ins_fmter("C.FLDSP f%1$d, %2%(x2)");
8196
+    	    ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_uimm_val;
8197
+    	    std::vector<llvm::Value*> args {
8198
+    	        this->core_ptr,
8199
+    	        this->gen_const(64, pc.val),
8200
+    	        this->builder.CreateGlobalStringPtr(ins_fmter.str()),
8201
+    	    };
8202
+    	    this->builder.CreateCall(this->mod->getFunction("print_disass"), args);
8203
+    	}
8204
+    	
8205
+    	Value* cur_pc_val = this->gen_const(32, pc.val);
8206
+    	pc=pc+2;
8207
+    	
8208
+    	uint8_t x2_idx_val = 2;
8209
+    	Value* offs_val = this->builder.CreateAdd(
8210
+    	    this->gen_reg_load(x2_idx_val + traits<ARCH>::X0, 0),
8211
+    	    this->gen_const(32U, fld_uimm_val));
8212
+    	Value* res_val = this->gen_read_mem(traits<ARCH>::MEM, offs_val, 64/8);
8213
+    	if(64 == 64){
8214
+    	    Value* F_rd_val = res_val;
8215
+    	    this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits<ARCH>::F0), false);
8216
+    	} else {
8217
+    	    uint64_t upper_val = (-1);
8218
+    	    Value* F_rd_val = this->builder.CreateOr(
8219
+    	        this->builder.CreateShl(
8220
+    	            this->gen_const(64U, upper_val),
8221
+    	            this->gen_const(64U, 64)),
8222
+    	        this->gen_ext(
8223
+    	            res_val,
8224
+    	            64,
8225
+    	            false));
8226
+    	    this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits<ARCH>::F0), false);
8227
+    	}
8228
+    	this->gen_set_pc(pc, traits<ARCH>::NEXT_PC);
8229
+    	this->gen_sync(iss::POST_SYNC, 157);
8230
+    	bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */
8231
+    	this->gen_trap_check(bb);
8232
+    	return std::make_tuple(vm::CONT, bb);
8233
+    }
8234
+    
8235
+    /* instruction 158: C.FSDSP */
8236
+    std::tuple<vm::continuation_e, llvm::BasicBlock*> __c_fsdsp(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){
8237
+    	bb->setName("C.FSDSP");
8238
+    	
8239
+    	this->gen_sync(iss::PRE_SYNC, 158);
8240
+    	
8241
+    	uint8_t fld_rs2_val = 0 | (bit_sub<2,5>(instr));
8242
+    	uint16_t fld_uimm_val = 0 | (bit_sub<7,3>(instr) << 6) | (bit_sub<10,3>(instr) << 3);
8243
+    	if(this->disass_enabled){
8244
+    	    /* generate console output when executing the command */
8245
+    	    boost::format ins_fmter("C.FSDSP f%1$d, %2%(x2), ");
8246
+    	    ins_fmter % (uint64_t)fld_rs2_val % (uint64_t)fld_uimm_val;
8247
+    	    std::vector<llvm::Value*> args {
8248
+    	        this->core_ptr,
8249
+    	        this->gen_const(64, pc.val),
8250
+    	        this->builder.CreateGlobalStringPtr(ins_fmter.str()),
8251
+    	    };
8252
+    	    this->builder.CreateCall(this->mod->getFunction("print_disass"), args);
8253
+    	}
8254
+    	
8255
+    	Value* cur_pc_val = this->gen_const(32, pc.val);
8256
+    	pc=pc+2;
8257
+    	
8258
+    	uint8_t x2_idx_val = 2;
8259
+    	Value* offs_val = this->builder.CreateAdd(
8260
+    	    this->gen_reg_load(x2_idx_val + traits<ARCH>::X0, 0),
8261
+    	    this->gen_const(32U, fld_uimm_val));
8262
+    	Value* MEM_offs_val = this->builder.CreateTrunc(
8263
+    	    this->gen_reg_load(fld_rs2_val + traits<ARCH>::F0, 0),
8264
+    	    this-> get_type(64) 
8265
+    	);
8266
+    	this->gen_write_mem(
8267
+    	    traits<ARCH>::MEM,
8268
+    	    offs_val,
8269
+    	    this->builder.CreateZExtOrTrunc(MEM_offs_val,this->get_type(64)));
8270
+    	this->gen_set_pc(pc, traits<ARCH>::NEXT_PC);
8271
+    	this->gen_sync(iss::POST_SYNC, 158);
8272
+    	bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */
8273
+    	this->gen_trap_check(bb);
8274
+    	return std::make_tuple(vm::CONT, bb);
8275
+    }
8276
+    
8099 8277
     /****************************************************************************
8100 8278
      * end opcode definitions
8101 8279
      ****************************************************************************/