Skip to content
This repository was archived by the owner on Jan 25, 2022. It is now read-only.

Commit e097b23

Browse files
author
f74064054@mail.ncku.edu.tw
committed
Add the compressed C.NOP, C.ADDi and modify the get_insn32 function
Add the C.JAL and C.ADDIW insn
1 parent 6dde6b8 commit e097b23

File tree

1 file changed

+107
-14
lines changed

1 file changed

+107
-14
lines changed

emu-rv32i.c

Lines changed: 107 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,10 @@ original copyright:
9494
#define DEBUG_EXTRA
9595
#endif
9696

97+
#if 1
98+
#define RV32C
99+
#endif
100+
97101
/* added by Shaos: */
98102
#define STRICT_RV32I
99103
#define FALSE (0)
@@ -216,12 +220,18 @@ int machine_running = TRUE;
216220
#define PRV_H 2
217221
#define PRV_M 3
218222

223+
/* Instruction state*/
224+
#define CINSN 1
225+
#define INSN 0
226+
unsigned char insn_type;
227+
219228
/* CPU state */
220229
uint32_t pc;
221230
uint32_t next_pc;
222231
uint32_t insn;
223232
uint32_t reg[32];
224233

234+
225235
uint8_t priv = PRV_M; /* see PRV_x */
226236
uint8_t fs; /* MSTATUS_FS value */
227237
uint8_t mxl; /* MXL field in MISA register */
@@ -770,7 +780,7 @@ int raise_interrupt()
770780

771781
/* read 32-bit instruction from memory by PC */
772782

773-
uint32_t get_insn32(uint32_t pc)
783+
uint32_t get_insn32(uint32_t pc, uint32_t *insn)
774784
{
775785
#ifdef DEBUG_EXTRA
776786
if(pc && pc < minmemr) minmemr = pc;
@@ -779,9 +789,14 @@ uint32_t get_insn32(uint32_t pc)
779789
uint32_t ptr = pc - ram_start;
780790
if (ptr > RAM_SIZE) return 1;
781791
uint8_t* p = ram + ptr;
782-
if((p[0] & 0x03) < 3)
783-
return p[0] | (p[1] << 8);
784-
return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
792+
#ifdef RV32C
793+
if((p[0] & 0x03) < 3){
794+
*insn = (p[0] | (p[1] << 8)) & 0x0000ffff;
795+
return CINSN;
796+
}
797+
#endif
798+
*insn = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
799+
return INSN;
785800
}
786801

787802
/* read 8-bit data from memory */
@@ -1055,10 +1070,22 @@ void execute_instruction()
10551070
int32_t imm, cond, err;
10561071
uint32_t addr, val=0, val2;
10571072

1058-
opcode = insn & 0x7f;
1059-
rd = (insn >> 7) & 0x1f;
1060-
rs1 = (insn >> 15) & 0x1f;
1061-
rs2 = (insn >> 20) & 0x1f;
1073+
uint16_t midpart;
1074+
1075+
if(insn_type == INSN){
1076+
opcode = insn & 0x7f;
1077+
rd = (insn >> 7) & 0x1f;
1078+
rs1 = (insn >> 15) & 0x1f;
1079+
rs2 = (insn >> 20) & 0x1f;
1080+
}
1081+
1082+
#ifdef RV32C
1083+
if(insn_type == CINSN){
1084+
opcode = insn & 0x3;
1085+
}
1086+
#endif
1087+
1088+
10621089

10631090
switch(opcode) {
10641091

@@ -1906,10 +1933,72 @@ void execute_instruction()
19061933
break;
19071934

19081935
#endif
1909-
#ifndef RV32C
1910-
1911-
case 1: /* Compressed insn */
1912-
1936+
#ifdef RV32C
1937+
/* Compressed insn */
1938+
case 0:
1939+
break;
1940+
case 1:
1941+
funct3 = (insn >> 13) & 0x7;
1942+
midpart = (insn >> 2) & 0x07ff;
1943+
switch(funct3){
1944+
case 0: /* C.NOP, C.ADDI */
1945+
if( ((midpart >> 5) & 0x1f) == 0){ /* C.NOP*/
1946+
return;
1947+
} else {
1948+
rs1 = rd = (midpart >> 5) & 0x1f;
1949+
imm = (midpart & 0x1f) | ((midpart >> 5) & 0x20);
1950+
val = reg[rs1] + imm;
1951+
}
1952+
break;
1953+
case 1: /* C.JAL, C.ADDIW */
1954+
switch(XLEN){
1955+
case 32:
1956+
imm = (midpart & 0x400) |
1957+
((midpart << 3) & 0x200) |
1958+
(midpart & 0x170) |
1959+
((midpart << 2) & 0x40) |
1960+
(midpart & 0x20) |
1961+
((midpart << 4) & 0x10) |
1962+
((midpart >> 6) & 0x8) |
1963+
((midpart >> 1) & 0x7);
1964+
imm = imm & 0xfffe;
1965+
if (rd != 0)
1966+
reg[1] = pc + 2; /* Store the link to x1 register */
1967+
next_pc = (int32_t)(pc + imm);
1968+
if(next_pc > pc) forward_counter++;
1969+
else backward_counter++;
1970+
jump_counter++;
1971+
break;
1972+
case 64:
1973+
case 128:
1974+
rs1 = rd = (midpart >> 5) & 0x1f;
1975+
imm = (midpart >> (11 - 5)) |
1976+
midpart & 0x1f;
1977+
val = reg[rs1] + imm;
1978+
break;
1979+
}
1980+
break;
1981+
case 2: /* C.LI */
1982+
break;
1983+
case 3: /* C.ADDI16SP, C.LUI */
1984+
break;
1985+
case 4: /* C.SRLI, C.SRLI64, C.SRAI, C.SRAI64, C.ANDI, C.SUB, C.XOR, C.OR, C.AND, C.SUBW, C.ADDW*/
1986+
break;
1987+
case 5: /* C.J */
1988+
break;
1989+
case 6: /* C.BEQZ */
1990+
break;
1991+
case 7: /* C.BNEZ */
1992+
break;
1993+
default:
1994+
raise_exception(CAUSE_ILLEGAL_INSTRUCTION, insn);
1995+
return;
1996+
}
1997+
if(rd != 0){
1998+
reg[rd] = val;
1999+
}
2000+
break;
2001+
case 2:
19132002
break;
19142003

19152004
#endif
@@ -1950,8 +2039,12 @@ void riscv_cpu_interp_x32()
19502039
if ((mip & mie) != 0 && (mstatus & MSTATUS_MIE)) {
19512040
raise_interrupt();
19522041
} else {
1953-
/* normal instruction execution */
1954-
insn = get_insn32(pc);
2042+
/* Compressed or normal */
2043+
insn_type = get_insn32(pc, &insn);
2044+
#ifdef RV32C
2045+
if(insn_type)
2046+
next_pc = pc + 2;
2047+
#endif
19552048
#ifdef DEBUG_EXTRA
19562049
printf("insn : %#x\n", insn);
19572050
#endif

0 commit comments

Comments
 (0)