blockmem.isa revision 3274
1////////////////////////////////////////////////////////////////////
2//
3// Block Memory instructions
4//
5
6output header {{
7
8        class BlockMem : public SparcMacroInst
9        {
10          protected:
11
12            // Constructor
13            // We make the assumption that all block memory operations
14            // Will take 8 instructions to execute
15            BlockMem(const char *mnem,
16                    ExtMachInst _machInst, OpClass __opClass) :
17                SparcMacroInst(mnem, _machInst, __opClass, 8)
18            {}
19
20            std::string generateDisassembly(Addr pc,
21                const SymbolTable *symtab) const;
22        };
23
24        class BlockMemImm : public BlockMem
25        {
26          protected:
27
28            // Constructor
29            BlockMemImm(const char *mnem,
30                    ExtMachInst _machInst, OpClass __opClass) :
31                BlockMem(mnem, _machInst, __opClass),
32                imm(sext<13>(SIMM13))
33            {}
34
35            std::string generateDisassembly(Addr pc,
36                const SymbolTable *symtab) const;
37
38            const int32_t imm;
39        };
40
41        class BlockMemMicro : public SparcDelayedMicroInst
42        {
43          protected:
44
45            // Constructor
46            BlockMemMicro(const char *mnem, ExtMachInst _machInst,
47                    OpClass __opClass, int8_t _offset) :
48                SparcDelayedMicroInst(mnem, _machInst, __opClass),
49                offset(_offset)
50            {}
51
52            std::string generateDisassembly(Addr pc,
53                const SymbolTable *symtab) const;
54
55            const int8_t offset;
56        };
57
58        class BlockMemImmMicro : public BlockMemMicro
59        {
60          protected:
61
62            // Constructor
63            BlockMemImmMicro(const char *mnem, ExtMachInst _machInst,
64                    OpClass __opClass, int8_t _offset) :
65                BlockMemMicro(mnem, _machInst, __opClass, _offset),
66                imm(sext<13>(SIMM13))
67            {}
68
69            std::string generateDisassembly(Addr pc,
70                const SymbolTable *symtab) const;
71
72            const int32_t imm;
73        };
74}};
75
76output decoder {{
77        std::string BlockMem::generateDisassembly(Addr pc,
78                const SymbolTable *symtab) const
79        {
80            std::stringstream response;
81            bool load = flags[IsLoad];
82            bool save = flags[IsStore];
83
84            printMnemonic(response, mnemonic);
85            if(save)
86            {
87                printReg(response, _srcRegIdx[0]);
88                ccprintf(response, ", ");
89            }
90            ccprintf(response, "[ ");
91            printReg(response, _srcRegIdx[!save ? 0 : 1]);
92            ccprintf(response, " + ");
93            printReg(response, _srcRegIdx[!save ? 1 : 2]);
94            ccprintf(response, " ]");
95            if(load)
96            {
97                ccprintf(response, ", ");
98                printReg(response, _destRegIdx[0]);
99            }
100
101            return response.str();
102        }
103
104        std::string BlockMemImm::generateDisassembly(Addr pc,
105                const SymbolTable *symtab) const
106        {
107            std::stringstream response;
108            bool load = flags[IsLoad];
109            bool save = flags[IsStore];
110
111            printMnemonic(response, mnemonic);
112            if(save)
113            {
114                printReg(response, _srcRegIdx[0]);
115                ccprintf(response, ", ");
116            }
117            ccprintf(response, "[ ");
118            printReg(response, _srcRegIdx[!save ? 0 : 1]);
119            if(imm >= 0)
120                ccprintf(response, " + 0x%x ]", imm);
121            else
122                ccprintf(response, " + -0x%x ]", -imm);
123            if(load)
124            {
125                ccprintf(response, ", ");
126                printReg(response, _destRegIdx[0]);
127            }
128
129            return response.str();
130        }
131
132}};
133
134def template LoadStoreExecute {{
135        Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
136                Trace::InstRecord *traceData) const
137        {
138            Fault fault = NoFault;
139            uint64_t write_result = 0;
140            Addr EA;
141            %(op_decl)s;
142            %(op_rd)s;
143            %(priv_check)s;
144            %(ea_code)s;
145            DPRINTF(Sparc, "The address is 0x%x\n", EA);
146            xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, 0);
147            %(code)s;
148
149            if(fault == NoFault)
150            {
151                xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result);
152                //Write the resulting state to the execution context
153                %(op_wb)s;
154            }
155
156            return fault;
157        }
158}};
159
160def template BlockMemDeclare {{
161        /**
162         * Static instruction class for a block memory operation
163         */
164        class %(class_name)s : public %(base_class)s
165        {
166          public:
167            //Constructor
168            %(class_name)s(MachInst machInst);
169
170          protected:
171            class %(class_name)s_0 : public %(base_class)sMicro
172            {
173              public:
174                //Constructor
175                %(class_name)s_0(MachInst machInst) :
176                    %(base_class)sMicro("%(mnemonic)s[0]",
177                            machInst, %(op_class)s, 0*8)
178                {;}
179                %(BasicExecDeclare)s
180            };
181
182            class %(class_name)s_1 : public %(base_class)sMicro
183            {
184              public:
185                //Constructor
186                %(class_name)s_1(MachInst machInst) :
187                    %(base_class)sMicro("%(mnemonic)s[1]",
188                            machInst, %(op_class)s, 1*8)
189                {;}
190                %(BasicExecDeclare)s
191            };
192
193            class %(class_name)s_2 : public %(base_class)sMicro
194            {
195              public:
196                //Constructor
197                %(class_name)s_2(MachInst machInst) :
198                    %(base_class)sMicro("%(mnemonic)s[2]",
199                            machInst, %(op_class)s, 2*8)
200                {;}
201                %(BasicExecDeclare)s
202            };
203
204            class %(class_name)s_3 : public %(base_class)sMicro
205            {
206              public:
207                //Constructor
208                %(class_name)s_3(MachInst machInst) :
209                    %(base_class)sMicro("%(mnemonic)s[3]",
210                            machInst, %(op_class)s, 3*8)
211                {;}
212                %(BasicExecDeclare)s
213            };
214
215            class %(class_name)s_4 : public %(base_class)sMicro
216            {
217              public:
218                //Constructor
219                %(class_name)s_4(MachInst machInst) :
220                    %(base_class)sMicro("%(mnemonic)s[4]",
221                            machInst, %(op_class)s, 4*8)
222                {;}
223                %(BasicExecDeclare)s
224            };
225
226            class %(class_name)s_5 : public %(base_class)sMicro
227            {
228              public:
229                //Constructor
230                %(class_name)s_5(MachInst machInst) :
231                    %(base_class)sMicro("%(mnemonic)s[5]",
232                            machInst, %(op_class)s, 5*8)
233                {;}
234                %(BasicExecDeclare)s
235            };
236
237            class %(class_name)s_6 : public %(base_class)sMicro
238            {
239              public:
240                //Constructor
241                %(class_name)s_6(MachInst machInst) :
242                    %(base_class)sMicro("%(mnemonic)s[6]",
243                            machInst, %(op_class)s, 6*8)
244                {;}
245                %(BasicExecDeclare)s
246            };
247
248            class %(class_name)s_7 : public %(base_class)sMicro
249            {
250              public:
251                //Constructor
252                %(class_name)s_7(MachInst machInst) :
253                    %(base_class)sMicro("%(mnemonic)s[7]",
254                            machInst, %(op_class)s, 7*8)
255                {
256                    flags[IsLastMicroOp] = true;
257                }
258                %(BasicExecDeclare)s
259            };
260        };
261}};
262
263// Basic instruction class constructor template.
264def template BlockMemConstructor {{
265        inline %(class_name)s::%(class_name)s(MachInst machInst)
266            : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
267        {
268            %(constructor)s;
269            microOps[0] = new %(class_name)s_0(machInst);
270            microOps[1] = new %(class_name)s_1(machInst);
271            microOps[2] = new %(class_name)s_2(machInst);
272            microOps[3] = new %(class_name)s_3(machInst);
273            microOps[4] = new %(class_name)s_4(machInst);
274            microOps[5] = new %(class_name)s_5(machInst);
275            microOps[6] = new %(class_name)s_6(machInst);
276            microOps[7] = new %(class_name)s_7(machInst);
277        }
278}};
279
280def template MicroLoadExecute {{
281        Fault %(class_name)s_%(micro_pc)s::execute(%(CPU_exec_context)s *xc,
282                Trace::InstRecord *traceData) const
283        {
284            Fault fault = NoFault;
285            Addr EA;
286            %(op_decl)s;
287            %(op_rd)s;
288            %(fault_check)s;
289            %(ea_code)s;
290            DPRINTF(Sparc, "The address is 0x%x\n", EA);
291            xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, 0);
292            %(code)s;
293
294            if(fault == NoFault)
295            {
296                //Write the resulting state to the execution context
297                %(op_wb)s;
298            }
299
300            return fault;
301        }
302}};
303
304def template MicroStoreExecute {{
305        Fault %(class_name)s_%(micro_pc)s::execute(%(CPU_exec_context)s *xc,
306                Trace::InstRecord *traceData) const
307        {
308            Fault fault = NoFault;
309            uint64_t write_result = 0;
310            Addr EA;
311            %(op_decl)s;
312            %(op_rd)s;
313            %(fault_check)s;
314            %(ea_code)s;
315            DPRINTF(Sparc, "The address is 0x%x\n", EA);
316            %(code)s;
317
318            if(fault == NoFault)
319            {
320                xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result);
321                //Write the resulting state to the execution context
322                %(op_wb)s;
323            }
324
325            return fault;
326        }
327}};
328
329let {{
330
331    def doBlockMemFormat(code, execute, name, Name, opt_flags):
332        # XXX Need to take care of pstate.hpriv as well. The lower ASIs
333        # are split into ones that are available in priv and hpriv, and
334        # those that are only available in hpriv
335        faultCheck = '''if(bits(Pstate,2,2) == 0 && (EXT_ASI & 0x80) == 0)
336                    return new PrivilegedAction;
337                if(AsiIsAsIfUser(EXT_ASI) && !bits(Pstate,2,2))
338                    return new PrivilegedAction;
339                if(RD & 0xf)
340                    return new IllegalInstruction;
341                if(EA & 0x3f)
342                    return new MemAddressNotAligned;'''
343        addrCalcReg = 'EA = Rs1 + Rs2 + offset;'
344        addrCalcImm = 'EA = Rs1 + imm + offset;'
345        iop = InstObjParams(name, Name, 'BlockMem', code, opt_flags)
346        iop_imm = InstObjParams(name, Name + 'Imm', 'BlockMemImm', code, opt_flags)
347        header_output = BlockMemDeclare.subst(iop) + BlockMemDeclare.subst(iop_imm)
348        decoder_output = BlockMemConstructor.subst(iop) + BlockMemConstructor.subst(iop_imm)
349        decode_block = ROrImmDecode.subst(iop)
350        matcher = re.compile(r'Frd_N')
351        exec_output = ''
352        for microPC in range(8):
353            pcedCode = matcher.sub("Frd_%d" % microPC, code)
354            iop = InstObjParams(name, Name, 'BlockMem', pcedCode,
355                    opt_flags, {"ea_code": addrCalcReg,
356                    "fault_check": faultCheck, "micro_pc": microPC})
357            iop_imm = InstObjParams(name, Name + 'Imm', 'BlockMemImm', pcedCode,
358                    opt_flags, {"ea_code": addrCalcImm,
359                    "fault_check": faultCheck, "micro_pc": microPC})
360            exec_output += execute.subst(iop)
361            exec_output += execute.subst(iop_imm)
362            faultCheck = ''
363        return (header_output, decoder_output, exec_output, decode_block)
364}};
365
366def format BlockLoad(code, *opt_flags) {{
367        (header_output,
368         decoder_output,
369         exec_output,
370         decode_block) = doBlockMemFormat(code, MicroLoadExecute,
371             name, Name, opt_flags)
372}};
373
374def format BlockStore(code, *opt_flags) {{
375        (header_output,
376         decoder_output,
377         exec_output,
378         decode_block) = doBlockMemFormat(code, MicroStoreExecute,
379            name, Name, opt_flags)
380}};
381