diff --git a/riscv64.c b/riscv64.c index 01ddece..47dc8e7 100644 --- a/riscv64.c +++ b/riscv64.c @@ -132,7 +132,11 @@ void riscv64_disassemble_one(const RISCV64 *r) { case 0b1100011: { PARSE_B_INS(ins); - if (funct3 == 0b100) { + if (funct3 == 0b000) { + printf("beq %s, %s, %d\n", REGS[rs1], REGS[rs2], imm); + } else if (funct3 == 0b001) { + printf("bne %s, %s, %d\n", REGS[rs1], REGS[rs2], imm); + } else if (funct3 == 0b100) { printf("blt %s, %s, %d\n", REGS[rs1], REGS[rs2], imm); } else if (funct3 == 0b101) { printf("bge %s, %s, %d\n", REGS[rs1], REGS[rs2], imm); @@ -147,6 +151,8 @@ void riscv64_disassemble_one(const RISCV64 *r) { if (funct3 == 0b000) { printf("addi %s, %s, %d\n", REGS[rd], REGS[rs1], imm); + } else if (funct3 == 0b001) { + printf("slli %s, %s, %d\n", REGS[rd], REGS[rs1], imm); } else { fprintf(stderr, "I-type 1: unrecognized funct3: %03b\n", funct3); exit(1); @@ -157,6 +163,8 @@ void riscv64_disassemble_one(const RISCV64 *r) { if (funct3 == 0b000) { printf("lb %s, %d(%s)\n", REGS[rd], imm, REGS[rs1]); + } else if (funct3 == 0b011) { + printf("ld %s, %d(%s)\n", REGS[rd], imm, REGS[rs1]); } else { fprintf(stderr, "I-type 2: unrecognized funct3: %03b\n", funct3); exit(1); @@ -189,8 +197,12 @@ void riscv64_disassemble_one(const RISCV64 *r) { case 0b0110011: { PARSE_R_INS(ins); if (funct3 == 0b000) { - if (funct7 == 0) { + if (funct7 == 0b0000000) { printf("add %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]); + } else if (funct7 == 0b0100000) { + printf("sub %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]); + } else if (funct7 == 0b0000001) { + printf("mul %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]); } else { fprintf(stderr, "R-type 1: funct3=0b000: unrecognized funct7: %b\n", funct7); @@ -204,23 +216,49 @@ void riscv64_disassemble_one(const RISCV64 *r) { case 0b0101111: fprintf(stderr, "R-type 2: unimplemented\n"); exit(1); - case 0b0111011: - fprintf(stderr, "R-type 3: unimplemented\n"); - exit(1); + case 0b0111011: { + PARSE_R_INS(ins); + if (funct3 == 0b101) { + if (funct7 == 0b0000001) { + printf("divuw %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]); + } else { + fprintf(stderr, "R-type 3: funct3=101: unrecognized funct7: %b\n", + funct7); + exit(1); + } + } else if (funct3 == 0b111) { + printf("remuw %s, %s, %s\n", REGS[rd], REGS[rs1], REGS[rs2]); + } else { + fprintf(stderr, "R-type 3: unrecognized funct3: %03b\n", funct3); + exit(1); + } + }; break; + case 0b0011011: { + uint8_t funct3 = (ins >> 12) & 0b111; + if (funct3 == 0b000) { + PARSE_I_INS(ins); + printf("addiw %s, %s, %d\n", REGS[rd], REGS[rs1], imm); + } else { + fprintf(stderr, "R-type 4: unrecognized funct3: %03b\n", funct3); + exit(1); + } + }; break; case 0b0100011: { PARSE_S_INS(ins); if (funct3 == 0b000) { printf("sb %s, %d(%s)\n", REGS[rs2], imm, REGS[rs1]); + } else if (funct3 == 0b011) { + printf("sd %s, %d(%s)\n", REGS[rs2], imm, REGS[rs1]); } else { fprintf(stderr, "S-type: unrecognized funct3: %03b\n", funct3); exit(1); } }; break; - case 0b0110111: - fprintf(stderr, "U-type 1: unimplemented\n"); - exit(1); - break; + case 0b0110111: { + PARSE_U_INS(ins); + printf("lui %s, %d\n", REGS[rd], imm); + }; break; case 0b0010111: { PARSE_U_INS(ins); printf("auipc %s, %d\n", REGS[rd], imm); @@ -249,7 +287,17 @@ void riscv64_execute(RISCV64 *r) { case 0b1100011: { PARSE_B_INS(ins); - if (funct3 == 0b101) { // bge + if (funct3 == 0b000) { // beq + if (r->regs[rs1] == r->regs[rs2]) { + r->pc += imm; + continue; + } + } else if (funct3 == 0b001) { // bne + if (r->regs[rs1] != r->regs[rs2]) { + r->pc += imm; + continue; + } + } else if (funct3 == 0b101) { // bge if (r->regs[rs1] >= r->regs[rs2]) { r->pc += imm; continue; @@ -269,6 +317,8 @@ void riscv64_execute(RISCV64 *r) { if (funct3 == 0b000) { // addi r->regs[rd] = r->regs[rs1] + imm; + } else if (funct3 == 0b001) { // slli + r->regs[rd] = r->regs[rs1] << (imm & 0b111111); } else { fprintf(stderr, "I-type 1: unrecognized funct3: %03b\n", funct3); exit(1); @@ -279,6 +329,8 @@ void riscv64_execute(RISCV64 *r) { if (funct3 == 0b000) { // lb r->regs[rd] = r->memory[r->regs[rs1] + imm]; + } else if (funct3 == 0b011) { // ld + r->regs[rd] = *(uint64_t *)&r->memory[r->regs[rs1] + imm]; } else { fprintf(stderr, "I-type 2: unrecognized funct3: %03b\n", funct3); exit(1); @@ -314,6 +366,8 @@ void riscv64_execute(RISCV64 *r) { break; r->memory[start + i] = (uint8_t)c; bytes_read++; + if (c == '\n') + break; } r->regs[10] = bytes_read; @@ -335,6 +389,23 @@ void riscv64_execute(RISCV64 *r) { printf("Program exited with code %lu.\n", r->regs[10]); return; }; break; + case 169: { // gettimeofday + // TODO: actually return the time + int64_t tv_addr = r->regs[10]; + int64_t tz_addr = r->regs[11]; + + uint8_t tv_buf[16] = { + 0xD2, 0x02, 0x96, 0x49, + 0x00, 0x00, 0x00, 0x00, // tv_sec = 1234567890 + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, // tv_usec = 0 + }; + memcpy(&r->memory[tv_addr], tv_buf, 16); + + memset(&r->memory[tz_addr], 0, 8); + + r->regs[10] = 0; + }; break; default: fprintf(stderr, "Unimplemented syscall: %lu\n", r->regs[17]); exit(1); @@ -359,9 +430,15 @@ void riscv64_execute(RISCV64 *r) { case 0b0110011: { PARSE_R_INS(ins); if (funct3 == 0b000) { - if (funct7 == 0) { // add + if (funct7 == 0b0000000) { // add r->regs[rd] = r->regs[rs1] + r->regs[rs2]; break; + } else if (funct7 == 0b0100000) { // sub + r->regs[rd] = r->regs[rs1] - r->regs[rs2]; + break; + } else if (funct7 == 0b0000001) { // mul + r->regs[rd] = r->regs[rs1] * r->regs[rs2]; + break; } else { fprintf(stderr, "R-type 1: funct3=0b000: unrecognized funct7: %b\n", funct7); @@ -372,20 +449,64 @@ void riscv64_execute(RISCV64 *r) { exit(1); } }; break; + case 0b0111011: { + PARSE_R_INS(ins); + if (funct3 == 0b101) { + if (funct7 == 0b0000001) { + if (r->regs[rs2] == 0) { + r->regs[rd] = -1LL; + } else { + r->regs[rd] = (int32_t)(r->regs[rs1] / r->regs[rs2]); + } + } else { + fprintf(stderr, "R-type 3: funct3=101: unrecognized funct7: %b\n", + funct7); + exit(1); + } + } else if (funct3 == 0b111) { + if (r->regs[rs2] == 0) { + r->regs[rd] = (int32_t)r->regs[rs1]; + } else { + r->regs[rd] = (int32_t)(r->regs[rs1] % r->regs[rs2]); + } + } else { + fprintf(stderr, "R-type 3: unrecognized funct3: %03b\n", funct3); + exit(1); + } + }; break; + case 0b0011011: { + uint8_t funct3 = (ins >> 12) & 0b111; + if (funct3 == 0b000) { + PARSE_I_INS(ins); + int32_t result = r->regs[rs1] + imm; + r->regs[rd] = result; + } else { + fprintf(stderr, "R-type 4: unrecognized funct3: %03b\n", funct3); + exit(1); + } + }; break; case 0b0100011: { PARSE_S_INS(ins); if (funct3 == 0b000) { // sb size_t addr = r->regs[rs1] + imm; r->memory[addr] = r->regs[rs2]; + } else if (funct3 == 0b011) { // sd + size_t addr = r->regs[rs1] + imm; + // take this rust + *(uint64_t *)(&r->memory[addr]) = r->regs[rs2]; } else { fprintf(stderr, "S-type: unrecognized funct3: %03b\n", funct3); exit(1); } }; break; + case 0b0110111: { // lui + PARSE_U_INS(ins); + r->regs[rd] = imm << 12; + }; break; case 0b0010111: { // auipc PARSE_U_INS(ins); - r->regs[rd] = r->pc + (imm >> 12); + r->regs[rd] = r->pc + (imm << 12); }; break; default: fprintf(stderr, "Unrecognized opcode: %07b\n", opcode);