reorganise twin-predication
[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 int dest_offs = 0;
23 bool zeroing = false;
24 #ifdef INSN_CATEGORY_TWINPREDICATION
25 reg_t src_pred = ~0x0;
26 int src_offs = 0;
27 bool zeroingsrc = false;
28 #endif
29 sv_insn_t insn(p, bits, floatintmap, PRED_ARGS, OFFS_ARGS);
30 if (vlen > 0)
31 {
32 fprintf(stderr, "pre-ex reg %s %x rd %ld rs1 %ld rs2 %ld vlen %d\n",
33 xstr(INSN), INSNCODE, s_insn.rd(), s_insn.rs1(), s_insn.rs2(),
34 vlen);
35 #ifdef INSN_CATEGORY_TWINPREDICATION
36 src_pred = insn.predicate(s_insn.SRC_REG(), SRC_PREDINT, zeroingsrc);
37 #endif
38 #ifdef DEST_PREDINT
39 // use the ORIGINAL, i.e. NON-REDIRECTED, register here
40 dest_pred = insn.predicate(s_insn.DEST_REG(), DEST_PREDINT, zeroing);
41 #endif
42 }
43 // identify which regs have had their CSR entries set as vectorised.
44 // really could do with a macro for-loop here... oh well...
45 // integer ops, RD, RS1, RS2, RS3 (use sv_int_tb)
46 if (insn.sv_check_reg(true, 16))
47 {
48 fprintf(stderr, "reg %s %x rd %ld rs1 %ld rs2 %ld vlen %d\n",
49 xstr(INSN), INSNCODE, s_insn.rd(), s_insn.rs1(), s_insn.rs2(),
50 vlen);
51 }
52 // if vectorop is set, one of the regs is not a scalar,
53 // so we must read the VL CSR and do a loop
54 if (vlen == 0)
55 {
56 vlen = 1; // minimum of one loop
57 }
58 for (int voffs=0; voffs < vlen; voffs++)
59 {
60 insn.reset_vloop_check();
61 #ifdef INSN_CATEGORY_TWINPREDICATION
62 if (src_offs >= vlen) {
63 break;
64 }
65 if (dest_offs >= vlen) {
66 break;
67 }
68 #ifdef INSN_C_MV
69 fprintf(stderr, "pre twin reg %s src %d dest %d pred %lx %lx\n",
70 xstr(INSN), src_offs, dest_offs, src_pred, dest_pred);
71 #endif
72 if (!zeroingsrc)
73 {
74 while ((src_pred & (1<<src_offs)) == 0) {
75 src_offs += 1;
76 if (src_offs >= vlen) {
77 break;
78 }
79 }
80 }
81 if (!zeroing)
82 {
83 while ((dest_pred & (1<<dest_offs)) == 0) {
84 dest_offs += 1;
85 if (dest_offs >= vlen) {
86 break;
87 }
88 }
89 }
90 if (src_offs >= vlen || dest_offs >= vlen) {
91 break; // end vector loop if either src or dest pred reaches end
92 }
93 if (vlen > 1)
94 {
95 fprintf(stderr, "twin reg %s src %d dest %d pred %lx %lx\n",
96 xstr(INSN), src_offs, dest_offs, src_pred, dest_pred);
97 }
98 #endif
99 #ifdef INSN_C_MV
100 fprintf(stderr, "pre loop reg %s %x vloop %d %d %d" \
101 "vlen %d stop %d pred %lx rdv %lx rd %d rvc2 %d\n",
102 xstr(INSN), INSNCODE, voffs, src_offs, dest_offs,
103 vlen, insn.stop_vloop(),
104 dest_pred & (1<<voffs), READ_REG(insn._rd()),
105 insn._rd(), insn._rvc_rs2());
106 #endif
107 #include INCLUDEFILE
108 #ifdef DEST_PREDINT
109 // don't check inversion here as dest_pred has already been inverted
110 if (zeroing && ((dest_pred & (1<<dest_offs)) == 0))
111 {
112 // insn._rd() would be predicated: have to use insn._rd() here
113 WRITE_REG(insn._DEST_REG(), 0);
114 }
115 #endif
116 if (vlen > 1)
117 {
118 #if defined(USING_REG_RD)
119 fprintf(stderr, "reg %s %x vloop %d vlen %d stop %d pred %lx rd%lx\n",
120 xstr(INSN), INSNCODE, voffs, vlen, insn.stop_vloop(),
121 dest_pred & (1<<voffs), READ_REG(insn._rd()));
122 #endif
123 #if defined(USING_REG_FRD)
124 fprintf(stderr, "reg %s %x vloop %d vlen %d stop %d pred %lx rd%lx\n",
125 xstr(INSN), INSNCODE, voffs, vlen, insn.stop_vloop(),
126 dest_pred & (1<<voffs),
127 (READ_FREG(insn._rd())));
128 #endif
129 }
130 if (insn.stop_vloop())
131 {
132 break;
133 }
134 #ifdef INSN_CATEGORY_TWINPREDICATION
135 src_offs += 1;
136 #endif
137 dest_offs += 1;
138 }
139 #else
140 insn_t insn(bits);
141 #include INCLUDEFILE
142 #endif
143 trace_opcode(p, INSNCODE, insn);
144 return npc;
145 }
146