add in twin-predication identification
[riscv-isa-sim.git] / riscv / insn_template_sv.cc
1 // See LICENSE for license details.
2
3 #define xstr(s) str(s)
4 #define str(s) #s
5
6 reg_t FN(processor_t* p, insn_t s_insn, reg_t pc)
7 {
8 int xlen = ISASZ;
9 reg_t npc = sext_xlen(pc + insn_length(INSNCODE));
10 // messy way to do it: insn_t is used elsewhere in a union,
11 // so cannot create virtual functions.
12 // a workaround is to grab the bits from the insn_t
13 // and create an sv-variant. also an opportunity to pass
14 // in a stack of other things that are needed.
15 insn_bits_t bits = s_insn.bits();
16 #ifndef USING_NOREGS
17 int vlen = p->get_state()->vl;
18 // need to know if register is used as float or int.
19 // REGS_PATTERN is generated by id_regs.py (per opcode)
20 unsigned int floatintmap = REGS_PATTERN;
21 reg_t dest_pred = ~0x0;
22 #ifdef INSN_CATEGORY_TWINPREDICATION
23 reg_t src_pred = ~0x0;
24 #endif
25 sv_insn_t insn(p, bits, floatintmap,
26 dest_pred,
27 #ifdef INSN_CATEGORY_TWINPREDICATION
28 // twin-predication ONLY applies to dual-op operands: MV, FCVT, LD/ST.
29 // however we don't know which register any of those will use, so
30 // pass src_pred to each of rs1-3 and let the instruction sort it out.
31 src_pred, src_pred, src_pred
32 #else
33 dest_pred, dest_pred, dest_pred
34 #endif
35 );
36 bool zeroing;
37 #ifdef INSN_CATEGORY_TWINPREDICATION
38 #ifdef USING_REG_RS1
39 #define SRCREG s_insn.rs1()
40 #endif
41 #ifdef USING_REG_RS2
42 #define SRCREG s_insn.rs2()
43 #endif
44 #ifdef USING_REG_RS3
45 #define SRCREG s_insn.rs3()
46 #endif
47 #if (defined(USING_REG_RVC_RS1) || defined(USING_REG_RVC_RS1S))
48 #define SRCREG s_insn.rvc_rs1()
49 #endif
50 #if (defined(USING_REG_RVC_RS2) || defined(USING_REG_RVC_RS2S))
51 #define SRCREG s_insn.rvc_rs2()
52 #endif
53 src_pred = insn.predicate(SRCREG, floatintmap & (REG_RS1|REG_RS2|REG_RS3),
54 zeroing);
55 #endif
56 #if defined(USING_REG_RD) || defined(USING_REG_FRD)
57 // use the ORIGINAL, i.e. NON-REDIRECTED, register here
58 dest_pred = insn.predicate(s_insn.rd(), floatintmap & REG_RD, zeroing);
59 #endif
60 // identify which regs have had their CSR entries set as vectorised.
61 // really could do with a macro for-loop here... oh well...
62 // integer ops, RD, RS1, RS2, RS3 (use sv_int_tb)
63 if (insn.sv_check_reg(true, 16))
64 {
65 fprintf(stderr, "reg %s %x rd %ld rs1 %ld rs2 %ld vlen %d\n",
66 xstr(INSN), INSNCODE, s_insn.rd(), s_insn.rs1(), s_insn.rs2(),
67 vlen);
68 }
69 // if vectorop is set, one of the regs is not a scalar,
70 // so we must read the VL CSR and do a loop
71 if (vlen == 0)
72 {
73 vlen = 1; // minimum of one loop
74 }
75 for (int voffs=0; voffs < vlen; voffs++)
76 {
77 insn.reset_vloop_check();
78 #include INCLUDEFILE
79 #if defined(USING_REG_RD) || defined(USING_REG_FRD)
80 // don't check inversion here as dest_pred has already been inverted
81 if (zeroing && ((dest_pred & (1<<voffs)) == 0))
82 {
83 // insn._rd() would be predicated: have to use insn._rd() here
84 WRITE_REG(insn._rd(), 0);
85 }
86 #endif
87 if (vlen > 1)
88 {
89 #if defined(USING_REG_RD)
90 fprintf(stderr, "reg %s %x vloop %d vlen %d stop %d pred %lx rd%lx\n",
91 xstr(INSN), INSNCODE, voffs, vlen, insn.stop_vloop(),
92 dest_pred & (1<<voffs), READ_REG(insn._rd()));
93 #endif
94 #if defined(USING_REG_FRD)
95 fprintf(stderr, "reg %s %x vloop %d vlen %d stop %d pred %lx rd%lx\n",
96 xstr(INSN), INSNCODE, voffs, vlen, insn.stop_vloop(),
97 dest_pred & (1<<voffs),
98 (READ_FREG(insn._rd())));
99 #endif
100 }
101 insn.reset_caches(); // ready to increment offsets in next iteration
102 if (insn.stop_vloop())
103 {
104 break;
105 }
106 }
107 #else
108 insn_t insn(bits);
109 #include INCLUDEFILE
110 #endif
111 trace_opcode(p, INSNCODE, insn);
112 return npc;
113 }
114