First pass at adding Zcmp to rvcpp
This commit is contained in:
parent
8e7e8f4008
commit
410d002372
|
@ -15,6 +15,7 @@
|
|||
// - RV32I
|
||||
// - M
|
||||
// - C (also called Zca)
|
||||
// - Zcmp
|
||||
|
||||
// Use unsigned arithmetic everywhere, with explicit sign extension as required.
|
||||
static inline ux_t sext(ux_t bits, int sign_bit) {
|
||||
|
@ -97,6 +98,45 @@ static inline uint c_rs2_l(uint32_t instr) {
|
|||
return GETBITS(instr, 6, 2);
|
||||
}
|
||||
|
||||
static inline uint zcmp_n_regs(uint32_t instr) {
|
||||
uint rlist = GETBITS(instr, 7, 4);
|
||||
return rlist == 0xf ? 13 : rlist - 3;
|
||||
}
|
||||
|
||||
static inline uint zcmp_stack_adj(uint32_t instr) {
|
||||
uint nregs = zcmp_n_regs(instr);
|
||||
uint adj_base =
|
||||
nregs > 12 ? 0x40 :
|
||||
nregs > 8 ? 0x30 :
|
||||
nregs > 4 ? 0x20 : 0x10;
|
||||
return adj_base + 16 * GETBITS(instr, 3, 2);
|
||||
|
||||
}
|
||||
|
||||
static inline uint32_t zcmp_reg_mask(uint32_t instr) {
|
||||
uint32_t mask = 0;
|
||||
switch (zcmp_n_regs(instr)) {
|
||||
case 13: mask |= 1u << 27; // s11
|
||||
mask |= 1u << 26; // s10
|
||||
case 11: mask |= 1u << 25; // s9
|
||||
case 10: mask |= 1u << 24; // s8
|
||||
case 9: mask |= 1u << 23; // s7
|
||||
case 8: mask |= 1u << 22; // s6
|
||||
case 7: mask |= 1u << 21; // s5
|
||||
case 6: mask |= 1u << 20; // s4
|
||||
case 5: mask |= 1u << 19; // s3
|
||||
case 4: mask |= 1u << 18; // s2
|
||||
case 3: mask |= 1u << 9; // s1
|
||||
case 2: mask |= 1u << 8; // s0
|
||||
case 1: mask |= 1u << 1; // ra
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
static inline uint zcmp_s_mapping(uint s_raw) {
|
||||
return s_raw + 8 + 8 * ((s_raw & 0x6) == 0);
|
||||
}
|
||||
|
||||
struct RVCSR {
|
||||
enum {
|
||||
WRITE = 0,
|
||||
|
@ -500,6 +540,39 @@ struct RVCore {
|
|||
+ (GETBITS(instr, 12, 9) << 2)
|
||||
+ (GETBITS(instr, 8, 7) << 6);
|
||||
mem.w32(addr, regs[c_rs2_l(instr)]);
|
||||
// Zcmp:
|
||||
} else if (RVOPC_MATCH(instr, CM_PUSH)) {
|
||||
ux_t addr = regs[2];
|
||||
for (uint i = 31; i > 0; --i) {
|
||||
if (zcmp_reg_mask(instr) & (1u << i)) {
|
||||
addr -= 4;
|
||||
mem.w32(addr, regs[i]);
|
||||
}
|
||||
}
|
||||
regnum_rd = 2;
|
||||
rd_wdata = regs[2] - zcmp_stack_adj(instr);
|
||||
} else if (RVOPC_MATCH(instr, CM_POP) || RVOPC_MATCH(instr, CM_POPRET) || RVOPC_MATCH(instr, CM_POPRETZ)) {
|
||||
bool clear_a0 = RVOPC_MATCH(instr, CM_POPRETZ);
|
||||
bool ret = clear_a0 || RVOPC_MATCH(instr, CM_POPRET);
|
||||
ux_t addr = regs[2] + zcmp_stack_adj(instr);
|
||||
for (uint i = 31; i > 0; --i) {
|
||||
if (zcmp_reg_mask(instr) & (1u << i)) {
|
||||
addr -= 4;
|
||||
regs[i] = mem.r32(addr);
|
||||
}
|
||||
}
|
||||
if (clear_a0)
|
||||
regs[10] = 0;
|
||||
if (ret)
|
||||
pc_wdata = regs[1];
|
||||
regnum_rd = 2;
|
||||
rd_wdata = regs[2] + zcmp_stack_adj(instr);
|
||||
} else if (RVOPC_MATCH(instr, CM_MVSA01)) {
|
||||
regs[zcmp_s_mapping(GETBITS(instr, 9, 8))] = regs[10];
|
||||
regs[zcmp_s_mapping(GETBITS(instr, 4, 2))] = regs[11];
|
||||
} else if (RVOPC_MATCH(instr, CM_MVA01S)) {
|
||||
regs[10] = regs[zcmp_s_mapping(GETBITS(instr, 9, 8))];
|
||||
regs[11] = regs[zcmp_s_mapping(GETBITS(instr, 4, 2))];
|
||||
} else {
|
||||
instr_invalid = true;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue