diff --git a/README.md b/README.md index 909880e..40b94b4 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Java实现的RSIC-V教学虚拟机。采用RV32I指令集 +Java实现的RSIC-V教学虚拟机。采用RV32IM指令集 ponyvm-rv32i 构建打包 @@ -14,4 +14,4 @@ java -jar PonyVM-0.0.1.jar -f pi.bin C样例编译 采用了ESP32C3的工具链 riscv32-esp-elf-gcc -riscv32-esp-elf-gcc -march=rv32i loop.s -o loop.bin +riscv32-esp-elf-gcc -march=rv32im loop.s -o loop.bin diff --git a/src/main/java/com/ponyvm/soc/core/CPU.java b/src/main/java/com/ponyvm/soc/core/CPU.java index d87cb0f..be88edb 100644 --- a/src/main/java/com/ponyvm/soc/core/CPU.java +++ b/src/main/java/com/ponyvm/soc/core/CPU.java @@ -43,10 +43,10 @@ public boolean executeInstruction() { Instruction inst = InstructionDecode(pc); String instAddr = Integer.toUnsignedString(pc, 16); // 打印指令操作码 -// System.out.println(Integer.toUnsignedString(pc, 16) + ":" + inst.assemblyString); +// System.out.println(Integer.toUnsignedString(pc, 16) + ":" + inst.toAssemblyString()); switch (inst.opcode) { - // R-type instructions - case 0b0110011: // ADD / SUB / SLL / SLT / SLTU / XOR / SRL / SRA / OR / AND + // R-type instructions 包含 RVI RVM + case 0b0110011: // ADD / SUB / SLL / SLT / SLTU / XOR / SRL / SRA / OR / AND /MUL /MULH /MULHSU /MULHU /DIV /DIVU /REM /REMU rType(inst); break; @@ -101,7 +101,7 @@ public boolean executeInstruction() { */ private void rType(Instruction inst) { switch (inst.funct3) { - case 0b000: // ADD / SUB + case 0b000: // ADD / SUB /MUL switch (inst.funct7) { case 0b0000000: // ADD reg[inst.rd] = reg[inst.rs1] + reg[inst.rs2]; @@ -109,23 +109,55 @@ private void rType(Instruction inst) { case 0b0100000: // SUB reg[inst.rd] = reg[inst.rs1] - reg[inst.rs2]; break; + case 0b0000001: // MUL 有符号*有符号 低32位 + reg[inst.rd] = reg[inst.rs1] * reg[inst.rs2]; + break; } break; - case 0b001: // SLL - reg[inst.rd] = reg[inst.rs1] << reg[inst.rs2]; + case 0b001: // SLL /MULH + switch (inst.funct7) { + case 0b0000000: // SLL + reg[inst.rd] = reg[inst.rs1] << reg[inst.rs2]; + break; + case 0b0000001: // MULH 有符号*有符号 高32位 + reg[inst.rd] = (int) (((long) reg[inst.rs1]) * reg[inst.rs2] >> 32); + break; + } break; - case 0b010: // SLT - if (reg[inst.rs1] < reg[inst.rs2]) reg[inst.rd] = 1; - else reg[inst.rd] = 0; + case 0b010://SLT MULHSU + switch (inst.funct7) { + case 0b0000000: // SLT + if (reg[inst.rs1] < reg[inst.rs2]) reg[inst.rd] = 1; + else reg[inst.rd] = 0; + break; + case 0b0000001: // MULHSU 有符号*无符号 高32位 + reg[inst.rd] = (int) ((reg[inst.rs1] * Integer.toUnsignedLong(reg[inst.rs2])) >> 32); + break; + } break; case 0b011: // SLTU - if (Integer.toUnsignedLong(reg[inst.rs1]) < Integer.toUnsignedLong(reg[inst.rs2])) reg[inst.rd] = 1; - else reg[inst.rd] = 0; + switch (inst.funct7) { + case 0b0000000: //SLTU + if (Integer.toUnsignedLong(reg[inst.rs1]) < Integer.toUnsignedLong(reg[inst.rs2])) + reg[inst.rd] = 1; + else reg[inst.rd] = 0; + break; + case 0b0000001: // MULHU 无符号*无符号 高32位 + reg[inst.rd] = (int) ((Integer.toUnsignedLong(reg[inst.rs1]) * Integer.toUnsignedLong(reg[inst.rs2])) >> 32); + break; + } break; - case 0b100: // XOR - reg[inst.rd] = reg[inst.rs1] ^ reg[inst.rs2]; + case 0b100: // XOR /DIV + switch (inst.funct7) { + case 0b0000000: //XOR + reg[inst.rd] = reg[inst.rs1] ^ reg[inst.rs2]; + break; + case 0b0000001: // DIV + reg[inst.rd] = reg[inst.rs1] / reg[inst.rs2]; + break; + } break; - case 0b101: // SRL / SRA + case 0b101: // SRL / SRA /DIV switch (inst.funct7) { case 0b0000000: // SRL reg[inst.rd] = reg[inst.rs1] >>> reg[inst.rs2]; @@ -133,13 +165,30 @@ private void rType(Instruction inst) { case 0b0100000: // SRA reg[inst.rd] = reg[inst.rs1] >> reg[inst.rs2]; break; + case 0b0000001: // DIVU + reg[inst.rd] = (int) ((Integer.toUnsignedLong(reg[inst.rs1]) / Integer.toUnsignedLong(reg[inst.rs2]))); + break; } break; case 0b110: // OR - reg[inst.rd] = reg[inst.rs1] | reg[inst.rs2]; + switch (inst.funct7) { + case 0b0000000: // OR + reg[inst.rd] = reg[inst.rs1] | reg[inst.rs2]; + break; + case 0b0000001: // REM + reg[inst.rd] = reg[inst.rs1] % reg[inst.rs2]; + break; + } break; - case 0b111: // AND - reg[inst.rd] = reg[inst.rs1] & reg[inst.rs2]; + case 0b111: // AND /REMU + switch (inst.funct7) { + case 0b0000000: // AND + reg[inst.rd] = reg[inst.rs1] & reg[inst.rs2]; + break; + case 0b0000001: // REMU + reg[inst.rd] = (int) ((Integer.toUnsignedLong(reg[inst.rs1]) % Integer.toUnsignedLong(reg[inst.rs2]))); + break; + } break; } pc += 4; diff --git a/src/main/java/com/ponyvm/soc/core/Instruction.java b/src/main/java/com/ponyvm/soc/core/Instruction.java index 6041799..3a7cbb9 100644 --- a/src/main/java/com/ponyvm/soc/core/Instruction.java +++ b/src/main/java/com/ponyvm/soc/core/Instruction.java @@ -65,7 +65,7 @@ private int getImmJ(int instruction) { return (b20 << 20 | b12to19 << 12 | b11 << 11 | b1to10 << 1); } - private String toAssemblyString() { + public String toAssemblyString() { String instr = "", arg1 = "", arg2 = "", arg3 = ""; switch (opcode) { // R-type instructions diff --git a/src/main/java/com/ponyvm/soc/internal/ram/Memory.java b/src/main/java/com/ponyvm/soc/internal/ram/Memory.java index 9258524..c6d5204 100644 --- a/src/main/java/com/ponyvm/soc/internal/ram/Memory.java +++ b/src/main/java/com/ponyvm/soc/internal/ram/Memory.java @@ -2,13 +2,12 @@ import com.ponyvm.soc.internal.sysbus.Addressable; +/** + * 数据以小端进行保存 + */ public class Memory implements Addressable { private byte[] memory; - /** - * Constructor for Memory - * Initializes as a byte array of size given by argument - */ public Memory(int capacity) { memory = new byte[capacity]; } diff --git a/src/test/resources/pi.bin b/src/test/resources/pi.bin index 759652c..fd5e3ae 100755 Binary files a/src/test/resources/pi.bin and b/src/test/resources/pi.bin differ diff --git a/src/test/resources/pi.s b/src/test/resources/pi.s new file mode 100644 index 0000000..ab08d8d --- /dev/null +++ b/src/test/resources/pi.s @@ -0,0 +1,117 @@ + .file "pi.c" + .option nopic + .attribute arch, "rv32i2p1_m2p0" + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .text + .globl __muldf3 + .globl __floatsidf + .globl __divdf3 + .globl __adddf3 + .globl __fixdfsi + .align 2 + .globl main + .type main, @function +main: + addi sp,sp,-32 + sw ra,28(sp) + sw s0,24(sp) + sw s2,20(sp) + sw s3,16(sp) + addi s0,sp,32 + sw zero,-32(s0) + sw zero,-28(s0) + sw zero,-20(s0) + j .L2 +.L5: + lw a5,-20(s0) + andi a5,a5,1 + beq a5,zero,.L3 + lui a5,%hi(.LC0) + lw a4,%lo(.LC0)(a5) + lw a5,%lo(.LC0+4)(a5) + j .L4 +.L3: + lui a5,%hi(.LC1) + lw a4,%lo(.LC1)(a5) + lw a5,%lo(.LC1+4)(a5) +.L4: + lui a3,%hi(.LC2) + lw a2,%lo(.LC2)(a3) + lw a3,%lo(.LC2+4)(a3) + mv a0,a4 + mv a1,a5 + call __muldf3 + mv a4,a0 + mv a5,a1 + mv s2,a4 + mv s3,a5 + lw a5,-20(s0) + slli a5,a5,1 + addi a5,a5,1 + mv a0,a5 + call __floatsidf + mv a4,a0 + mv a5,a1 + mv a2,a4 + mv a3,a5 + mv a0,s2 + mv a1,s3 + call __divdf3 + mv a4,a0 + mv a5,a1 + mv a2,a4 + mv a3,a5 + lw a0,-32(s0) + lw a1,-28(s0) + call __adddf3 + mv a4,a0 + mv a5,a1 + sw a4,-32(s0) + sw a5,-28(s0) + lw a5,-20(s0) + addi a5,a5,1 + sw a5,-20(s0) +.L2: + lw a4,-20(s0) + li a5,8192 + addi a5,a5,1807 + ble a4,a5,.L5 + lui a5,%hi(.LC3) + lw a2,%lo(.LC3)(a5) + lw a3,%lo(.LC3+4)(a5) + lw a0,-32(s0) + lw a1,-28(s0) + call __muldf3 + mv a4,a0 + mv a5,a1 + mv a0,a4 + mv a1,a5 + call __fixdfsi + mv a5,a0 + mv a0,a5 + lw ra,28(sp) + lw s0,24(sp) + lw s2,20(sp) + lw s3,16(sp) + addi sp,sp,32 + jr ra + .size main, .-main + .section .rodata + .align 3 +.LC0: + .word 0 + .word -1074790400 + .align 3 +.LC1: + .word 0 + .word 1072693248 + .align 3 +.LC2: + .word 0 + .word 1074790400 + .align 3 +.LC3: + .word 0 + .word 1093567616 + .ident "GCC: (xPack GNU RISC-V Embedded GCC x86_64) 12.2.0" diff --git a/src/test/resources/short.bin b/src/test/resources/short.bin new file mode 100755 index 0000000..48b44b7 Binary files /dev/null and b/src/test/resources/short.bin differ diff --git a/src/test/resources/short.c b/src/test/resources/short.c new file mode 100644 index 0000000..af5746c --- /dev/null +++ b/src/test/resources/short.c @@ -0,0 +1,8 @@ +//short _sum[4096] = {32765,-32688,2688,5656,45656,4535,4556,56356}; +//short i = 13414; +//short j = 32123; +int main(void) +{ +int div1 = 32765; +return div1/2; +} \ No newline at end of file diff --git a/src/test/resources/short.s b/src/test/resources/short.s new file mode 100644 index 0000000..dcc5cbc --- /dev/null +++ b/src/test/resources/short.s @@ -0,0 +1,26 @@ + .file "short.c" + .option nopic + .attribute arch, "rv32i2p1_m2p0" + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .text + .align 2 + .globl main + .type main, @function +main: + addi sp,sp,-32 + sw s0,28(sp) + addi s0,sp,32 + li a5,32768 + addi a5,a5,-3 + sw a5,-20(s0) + lw a5,-20(s0) + srli a4,a5,31 + add a5,a4,a5 + srai a5,a5,1 + mv a0,a5 + lw s0,28(sp) + addi sp,sp,32 + jr ra + .size main, .-main + .ident "GCC: (xPack GNU RISC-V Embedded GCC x86_64) 12.2.0"