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