Add support for Zba, Zbb, Zbc, Zbs, Zbkb to rvcpp. Passes tests

This commit is contained in:
Luke Wren 2024-03-20 01:06:13 +00:00
parent e1bb341876
commit 55504fa8f3
1 changed files with 115 additions and 19 deletions

View File

@ -269,7 +269,7 @@ public:
case CSR_MTVEC: mtvec = data & 0xfffffffdu; break;
case CSR_MSCRATCH: mscratch = data; break;
case CSR_MEPC: mepc = data & 0xfffffffeu; break;
case CSR_MCAUSE: mcause = data & 0x800000ffu; break;
case CSR_MCAUSE: mcause = data & 0x8000000fu; break;
case CSR_MTVAL: break;
case CSR_MCYCLE: mcycle = data; break;
@ -383,16 +383,7 @@ struct RVCore {
rd_wdata = rs1 & rs2;
else
exception_cause = XCAUSE_INSTR_ILLEGAL;
}
else if (funct7 == 0b01'00000) {
if (funct3 == 0b000)
rd_wdata = rs1 - rs2;
else if (funct3 == 0b101)
rd_wdata = (sx_t)rs1 >> (rs2 & 0x1f);
else
exception_cause = XCAUSE_INSTR_ILLEGAL;
}
else if (funct7 == 0b00'00001) {
} else if (funct7 == 0b00'00001) {
if (funct3 < 0b100) {
sdx_t mul_op_a = rs1;
sdx_t mul_op_b = rs2;
@ -430,8 +421,66 @@ struct RVCore {
rd_wdata = rs2 ? rs1 % rs2 : rs1;
}
}
}
else {
} else if (funct7 == 0b01'00000) {
if (funct3 == 0b000)
rd_wdata = rs1 - rs2;
else if (funct3 == 0b100)
rd_wdata = rs1 ^ ~rs2; // Zbb xnor
else if (funct3 == 0b101)
rd_wdata = (sx_t)rs1 >> (rs2 & 0x1f);
else if (funct3 == 0b110)
rd_wdata = rs1 | ~rs2; // Zbb orn
else if (funct3 == 0b111)
rd_wdata = rs1 & ~rs2; // Zbb andn
else
exception_cause = XCAUSE_INSTR_ILLEGAL;
} else if (RVOPC_MATCH(instr, BCLR)) {
rd_wdata = rs1 & ~(1u << (rs2 & 0x1f));
} else if (RVOPC_MATCH(instr, BEXT)) {
rd_wdata = (rs1 >> (rs2 & 0x1f)) & 0x1u;
} else if (RVOPC_MATCH(instr, BINV)) {
rd_wdata = rs1 ^ (1u << (rs2 & 0x1f));
} else if (RVOPC_MATCH(instr, BSET)) {
rd_wdata = rs1 | (1u << (rs2 & 0x1f));
} else if (RVOPC_MATCH(instr, SH1ADD)) {
rd_wdata = (rs1 << 1) + rs2;
} else if (RVOPC_MATCH(instr, SH2ADD)) {
rd_wdata = (rs1 << 2) + rs2;
} else if (RVOPC_MATCH(instr, SH3ADD)) {
rd_wdata = (rs1 << 3) + rs2;
} else if (RVOPC_MATCH(instr, MAX)) {
rd_wdata = (sx_t)rs1 > (sx_t)rs2 ? rs1 : rs2;
} else if (RVOPC_MATCH(instr, MAXU)) {
rd_wdata = rs1 > rs2 ? rs1 : rs2;
} else if (RVOPC_MATCH(instr, MIN)) {
rd_wdata = (sx_t)rs1 < (sx_t)rs2 ? rs1 : rs2;
} else if (RVOPC_MATCH(instr, MINU)) {
rd_wdata = rs1 < rs2 ? rs1 : rs2;
} else if (RVOPC_MATCH(instr, ROR)) {
uint shamt = rs2 & 0x1f;
rd_wdata = shamt ? (rs1 >> shamt) | (rs1 << (32 - shamt)) : rs1;
} else if (RVOPC_MATCH(instr, ROL)) {
uint shamt = rs2 & 0x1f;
rd_wdata = shamt ? (rs1 << shamt) | (rs1 >> (32 - shamt)) : rs1;
} else if (RVOPC_MATCH(instr, PACK)) {
rd_wdata = (rs1 & 0xffffu) | (rs2 << 16);
} else if (RVOPC_MATCH(instr, PACKH)) {
rd_wdata = (rs1 & 0xffu) | ((rs2 & 0xffu) << 8);
} else if (RVOPC_MATCH(instr, CLMUL) || RVOPC_MATCH(instr, CLMULH) || RVOPC_MATCH(instr, CLMULR)) {
uint64_t product = 0;
for (int i = 0; i < 32; ++i) {
if (rs2 & (1u << i)) {
product ^= (uint64_t)rs1 << i;
}
}
if (RVOPC_MATCH(instr, CLMUL)) {
rd_wdata = product;
} else if (RVOPC_MATCH(instr, CLMULH)) {
rd_wdata = product >> 32;
} else {
rd_wdata = product >> 31;
}
} else {
exception_cause = XCAUSE_INSTR_ILLEGAL;
}
break;
@ -455,14 +504,61 @@ struct RVCore {
// shamt is regnum_rs2
if (funct7 == 0b00'00000 && funct3 == 0b001) {
rd_wdata = rs1 << regnum_rs2;
}
else if (funct7 == 0b00'00000 && funct3 == 0b101) {
} else if (funct7 == 0b00'00000 && funct3 == 0b101) {
rd_wdata = rs1 >> regnum_rs2;
}
else if (funct7 == 0b01'00000 && funct3 == 0b101) {
} else if (funct7 == 0b01'00000 && funct3 == 0b101) {
rd_wdata = (sx_t)rs1 >> regnum_rs2;
}
else {
} else if (RVOPC_MATCH(instr, BCLRI)) {
rd_wdata = rs1 & ~(1u << regnum_rs2);
} else if (RVOPC_MATCH(instr, BINVI)) {
rd_wdata = rs1 ^ (1u << regnum_rs2);
} else if (RVOPC_MATCH(instr, BSETI)) {
rd_wdata = rs1 | (1u << regnum_rs2);
} else if (RVOPC_MATCH(instr, CLZ)) {
rd_wdata = rs1 ? __builtin_clz(rs1) : 32;
} else if (RVOPC_MATCH(instr, CPOP)) {
rd_wdata = __builtin_popcount(rs1);
} else if (RVOPC_MATCH(instr, CTZ)) {
rd_wdata = rs1 ? __builtin_ctz(rs1) : 32;
} else if (RVOPC_MATCH(instr, SEXT_B)) {
rd_wdata = (rs1 & 0xffu) - ((rs1 & 0x80u) << 1);
} else if (RVOPC_MATCH(instr, SEXT_H)) {
rd_wdata = (rs1 & 0xffffu) - ((rs1 & 0x8000u) << 1);
} else if (RVOPC_MATCH(instr, ZIP)) {
ux_t accum = 0;
for (int i = 0; i < 32; ++i) {
if (rs1 & (1u << i)) {
accum |= 1u << ((i >> 4) | ((i & 0xf) << 1));
}
}
rd_wdata = accum;
} else if (RVOPC_MATCH(instr, UNZIP)) {
ux_t accum = 0;
for (int i = 0; i < 32; ++i) {
if (rs1 & (1u << i)) {
accum |= 1u << ((i >> 1) | ((i & 1) << 4));
}
}
rd_wdata = accum;
} else if (RVOPC_MATCH(instr, BEXTI)) {
rd_wdata = (rs1 >> regnum_rs2) & 0x1u;
} else if (RVOPC_MATCH(instr, BREV8)) {
rd_wdata =
((rs1 & 0x80808080u) >> 7) | ((rs1 & 0x01010101u) << 7) |
((rs1 & 0x40404040u) >> 5) | ((rs1 & 0x02020202u) << 5) |
((rs1 & 0x20202020u) >> 3) | ((rs1 & 0x04040404u) << 3) |
((rs1 & 0x10101010u) >> 1) | ((rs1 & 0x08080808u) << 1);
} else if (RVOPC_MATCH(instr, ORC_B)) {
rd_wdata =
(rs1 & 0xff000000u ? 0xff000000u : 0u) |
(rs1 & 0x00ff0000u ? 0x00ff0000u : 0u) |
(rs1 & 0x0000ff00u ? 0x0000ff00u : 0u) |
(rs1 & 0x000000ffu ? 0x000000ffu : 0u);
} else if (RVOPC_MATCH(instr, REV8)) {
rd_wdata = __builtin_bswap32(rs1);
} else if (RVOPC_MATCH(instr, RORI)) {
rd_wdata = regnum_rs2 ? ((rs1 << (32 - regnum_rs2)) | (rs1 >> regnum_rs2)) : rs1;
} else {
exception_cause = XCAUSE_INSTR_ILLEGAL;
}
}