ldstop.isa revision 5232:d3801ea2792e
112855Sgabeblack@google.com// Copyright (c) 2007 The Hewlett-Packard Development Company
212855Sgabeblack@google.com// All rights reserved.
312855Sgabeblack@google.com//
412855Sgabeblack@google.com// Redistribution and use of this software in source and binary forms,
512855Sgabeblack@google.com// with or without modification, are permitted provided that the
612855Sgabeblack@google.com// following conditions are met:
712855Sgabeblack@google.com//
812855Sgabeblack@google.com// The software must be used only for Non-Commercial Use which means any
912855Sgabeblack@google.com// use which is NOT directed to receiving any direct monetary
1012855Sgabeblack@google.com// compensation for, or commercial advantage from such use.  Illustrative
1112855Sgabeblack@google.com// examples of non-commercial use are academic research, personal study,
1212855Sgabeblack@google.com// teaching, education and corporate research & development.
1312855Sgabeblack@google.com// Illustrative examples of commercial use are distributing products for
1412855Sgabeblack@google.com// commercial advantage and providing services using the software for
1512855Sgabeblack@google.com// commercial advantage.
1612855Sgabeblack@google.com//
1712855Sgabeblack@google.com// If you wish to use this software or functionality therein that may be
1812855Sgabeblack@google.com// covered by patents for commercial use, please contact:
1912855Sgabeblack@google.com//     Director of Intellectual Property Licensing
2012855Sgabeblack@google.com//     Office of Strategy and Technology
2112855Sgabeblack@google.com//     Hewlett-Packard Company
2212855Sgabeblack@google.com//     1501 Page Mill Road
2312855Sgabeblack@google.com//     Palo Alto, California  94304
2412855Sgabeblack@google.com//
2512855Sgabeblack@google.com// Redistributions of source code must retain the above copyright notice,
2612855Sgabeblack@google.com// this list of conditions and the following disclaimer.  Redistributions
2712855Sgabeblack@google.com// in binary form must reproduce the above copyright notice, this list of
2812855Sgabeblack@google.com// conditions and the following disclaimer in the documentation and/or
2912855Sgabeblack@google.com// other materials provided with the distribution.  Neither the name of
3012855Sgabeblack@google.com// the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
3112855Sgabeblack@google.com// contributors may be used to endorse or promote products derived from
3212855Sgabeblack@google.com// this software without specific prior written permission.  No right of
3312855Sgabeblack@google.com// sublicense is granted herewith.  Derivatives of the software and
3412855Sgabeblack@google.com// output created using the software may be prepared, but only for
3512855Sgabeblack@google.com// Non-Commercial Uses.  Derivatives of the software may be shared with
3612855Sgabeblack@google.com// others provided: (i) the others agree to abide by the list of
3712855Sgabeblack@google.com// conditions herein which includes the Non-Commercial Use restrictions;
3812855Sgabeblack@google.com// and (ii) such Derivatives of the software include the above copyright
3912855Sgabeblack@google.com// notice to acknowledge the contribution from this software where
4012855Sgabeblack@google.com// applicable, this list of conditions and the disclaimer below.
4112855Sgabeblack@google.com//
4212855Sgabeblack@google.com// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4312855Sgabeblack@google.com// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
4412855Sgabeblack@google.com// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
4512855Sgabeblack@google.com// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
4612855Sgabeblack@google.com// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
4712855Sgabeblack@google.com// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
4812855Sgabeblack@google.com// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
4912855Sgabeblack@google.com// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
5012855Sgabeblack@google.com// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
5112855Sgabeblack@google.com// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
5212855Sgabeblack@google.com// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5312855Sgabeblack@google.com//
5412855Sgabeblack@google.com// Authors: Gabe Black
5512855Sgabeblack@google.com
5612855Sgabeblack@google.com//////////////////////////////////////////////////////////////////////////
5712855Sgabeblack@google.com//
5812855Sgabeblack@google.com// LdStOp Microop templates
5912855Sgabeblack@google.com//
6012855Sgabeblack@google.com//////////////////////////////////////////////////////////////////////////
6112855Sgabeblack@google.com
6212855Sgabeblack@google.com// LEA template
6312855Sgabeblack@google.com
6412855Sgabeblack@google.comdef template MicroLeaExecute {{
6512855Sgabeblack@google.com    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
6612855Sgabeblack@google.com          Trace::InstRecord *traceData) const
6712855Sgabeblack@google.com    {
6812855Sgabeblack@google.com        Fault fault = NoFault;
6912855Sgabeblack@google.com        Addr EA;
7012855Sgabeblack@google.com
7112855Sgabeblack@google.com        %(op_decl)s;
7212855Sgabeblack@google.com        %(op_rd)s;
7312855Sgabeblack@google.com        %(ea_code)s;
7412855Sgabeblack@google.com        DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
7512855Sgabeblack@google.com
7612855Sgabeblack@google.com        %(code)s;
7712855Sgabeblack@google.com        if(fault == NoFault)
7812855Sgabeblack@google.com        {
7912855Sgabeblack@google.com            %(op_wb)s;
8012855Sgabeblack@google.com        }
8112855Sgabeblack@google.com
8212855Sgabeblack@google.com        return fault;
8312855Sgabeblack@google.com    }
8412855Sgabeblack@google.com}};
8512855Sgabeblack@google.com
8612855Sgabeblack@google.comdef template MicroLeaDeclare {{
8712855Sgabeblack@google.com    class %(class_name)s : public %(base_class)s
8812855Sgabeblack@google.com    {
8912855Sgabeblack@google.com      protected:
90        void buildMe();
91
92      public:
93        %(class_name)s(ExtMachInst _machInst,
94                const char * instMnem,
95                bool isMicro, bool isDelayed, bool isFirst, bool isLast,
96                uint8_t _scale, RegIndex _index, RegIndex _base,
97                uint64_t _disp, uint8_t _segment,
98                RegIndex _data,
99                uint8_t _dataSize, uint8_t _addressSize);
100
101        %(class_name)s(ExtMachInst _machInst,
102                const char * instMnem,
103                uint8_t _scale, RegIndex _index, RegIndex _base,
104                uint64_t _disp, uint8_t _segment,
105                RegIndex _data,
106                uint8_t _dataSize, uint8_t _addressSize);
107
108        %(BasicExecDeclare)s
109    };
110}};
111
112// Load templates
113
114def template MicroLoadExecute {{
115    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
116          Trace::InstRecord *traceData) const
117    {
118        Fault fault = NoFault;
119        Addr EA;
120
121        %(op_decl)s;
122        %(op_rd)s;
123        %(ea_code)s;
124        DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
125
126        fault = read(xc, EA, Mem, (%(mem_flags)s) | segment);
127
128        if(fault == NoFault)
129        {
130            %(code)s;
131        }
132        if(fault == NoFault)
133        {
134            %(op_wb)s;
135        }
136
137        return fault;
138    }
139}};
140
141def template MicroLoadInitiateAcc {{
142    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc,
143            Trace::InstRecord * traceData) const
144    {
145        Fault fault = NoFault;
146        Addr EA;
147
148        %(op_decl)s;
149        %(op_rd)s;
150        %(ea_code)s;
151        DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
152
153        fault = read(xc, EA, Mem, (%(mem_flags)s) | segment);
154
155        return fault;
156    }
157}};
158
159def template MicroLoadCompleteAcc {{
160    Fault %(class_name)s::completeAcc(PacketPtr pkt,
161            %(CPU_exec_context)s * xc,
162            Trace::InstRecord * traceData) const
163    {
164        Fault fault = NoFault;
165
166        %(op_decl)s;
167        %(op_rd)s;
168
169        Mem = pkt->get<typeof(Mem)>();
170
171        %(code)s;
172
173        if(fault == NoFault)
174        {
175            %(op_wb)s;
176        }
177
178        return fault;
179    }
180}};
181
182// Store templates
183
184def template MicroStoreExecute {{
185    Fault %(class_name)s::execute(%(CPU_exec_context)s * xc,
186            Trace::InstRecord *traceData) const
187    {
188        Fault fault = NoFault;
189
190        Addr EA;
191        %(op_decl)s;
192        %(op_rd)s;
193        %(ea_code)s;
194        DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
195
196        %(code)s;
197
198        if(fault == NoFault)
199        {
200            fault = write(xc, Mem, EA, (%(mem_flags)s) | segment);
201            if(fault == NoFault)
202            {
203                %(op_wb)s;
204            }
205        }
206
207        return fault;
208    }
209}};
210
211def template MicroStoreInitiateAcc {{
212    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc,
213            Trace::InstRecord * traceData) const
214    {
215        Fault fault = NoFault;
216
217        Addr EA;
218        %(op_decl)s;
219        %(op_rd)s;
220        %(ea_code)s;
221        DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
222
223        %(code)s;
224
225        if(fault == NoFault)
226        {
227            fault = write(xc, Mem, EA, (%(mem_flags)s) | segment);
228            if(fault == NoFault)
229            {
230                %(op_wb)s;
231            }
232        }
233        return fault;
234    }
235}};
236
237def template MicroStoreCompleteAcc {{
238    Fault %(class_name)s::completeAcc(PacketPtr, %(CPU_exec_context)s * xc,
239            Trace::InstRecord * traceData) const
240    {
241        return NoFault;
242    }
243}};
244
245// Common templates
246
247//This delcares the initiateAcc function in memory operations
248def template InitiateAccDeclare {{
249    Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
250}};
251
252//This declares the completeAcc function in memory operations
253def template CompleteAccDeclare {{
254    Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const;
255}};
256
257def template MicroLdStOpDeclare {{
258    class %(class_name)s : public %(base_class)s
259    {
260      protected:
261        void buildMe();
262
263      public:
264        %(class_name)s(ExtMachInst _machInst,
265                const char * instMnem,
266                bool isMicro, bool isDelayed, bool isFirst, bool isLast,
267                uint8_t _scale, RegIndex _index, RegIndex _base,
268                uint64_t _disp, uint8_t _segment,
269                RegIndex _data,
270                uint8_t _dataSize, uint8_t _addressSize);
271
272        %(class_name)s(ExtMachInst _machInst,
273                const char * instMnem,
274                uint8_t _scale, RegIndex _index, RegIndex _base,
275                uint64_t _disp, uint8_t _segment,
276                RegIndex _data,
277                uint8_t _dataSize, uint8_t _addressSize);
278
279        %(BasicExecDeclare)s
280
281        %(InitiateAccDeclare)s
282
283        %(CompleteAccDeclare)s
284    };
285}};
286
287def template MicroLdStOpConstructor {{
288
289    inline void %(class_name)s::buildMe()
290    {
291        %(constructor)s;
292    }
293
294    inline %(class_name)s::%(class_name)s(
295            ExtMachInst machInst, const char * instMnem,
296            uint8_t _scale, RegIndex _index, RegIndex _base,
297            uint64_t _disp, uint8_t _segment,
298            RegIndex _data,
299            uint8_t _dataSize, uint8_t _addressSize) :
300        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
301                false, false, false, false,
302                _scale, _index, _base,
303                _disp, _segment, _data,
304                _dataSize, _addressSize, %(op_class)s)
305    {
306        buildMe();
307    }
308
309    inline %(class_name)s::%(class_name)s(
310            ExtMachInst machInst, const char * instMnem,
311            bool isMicro, bool isDelayed, bool isFirst, bool isLast,
312            uint8_t _scale, RegIndex _index, RegIndex _base,
313            uint64_t _disp, uint8_t _segment,
314            RegIndex _data,
315            uint8_t _dataSize, uint8_t _addressSize) :
316        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
317                isMicro, isDelayed, isFirst, isLast,
318                _scale, _index, _base,
319                _disp, _segment, _data,
320                _dataSize, _addressSize, %(op_class)s)
321    {
322        buildMe();
323    }
324}};
325
326let {{
327    class LdStOp(X86Microop):
328        def __init__(self, data, segment, addr, disp, dataSize, addressSize):
329            self.data = data
330            [self.scale, self.index, self.base] = addr
331            self.disp = disp
332            self.segment = segment
333            self.dataSize = dataSize
334            self.addressSize = addressSize
335
336        def getAllocator(self, *microFlags):
337            allocator = '''new %(class_name)s(machInst, mnemonic
338                    %(flags)s, %(scale)s, %(index)s, %(base)s,
339                    %(disp)s, %(segment)s, %(data)s,
340                    %(dataSize)s, %(addressSize)s)''' % {
341                "class_name" : self.className,
342                "flags" : self.microFlagsText(microFlags),
343                "scale" : self.scale, "index" : self.index,
344                "base" : self.base,
345                "disp" : self.disp,
346                "segment" : self.segment, "data" : self.data,
347                "dataSize" : self.dataSize, "addressSize" : self.addressSize}
348            return allocator
349}};
350
351let {{
352
353    # Make these empty strings so that concatenating onto
354    # them will always work.
355    header_output = ""
356    decoder_output = ""
357    exec_output = ""
358
359    calculateEA = "EA = SegBase + scale * Index + Base + disp;"
360
361    def defineMicroLoadOp(mnemonic, code, mem_flags=0):
362        global header_output
363        global decoder_output
364        global exec_output
365        global microopClasses
366        Name = mnemonic
367        name = mnemonic.lower()
368
369        # Build up the all register version of this micro op
370        iop = InstObjParams(name, Name, 'X86ISA::LdStOp',
371                {"code": code,
372                 "ea_code": calculateEA,
373                 "mem_flags": mem_flags})
374        header_output += MicroLdStOpDeclare.subst(iop)
375        decoder_output += MicroLdStOpConstructor.subst(iop)
376        exec_output += MicroLoadExecute.subst(iop)
377        exec_output += MicroLoadInitiateAcc.subst(iop)
378        exec_output += MicroLoadCompleteAcc.subst(iop)
379
380        class LoadOp(LdStOp):
381            def __init__(self, data, segment, addr, disp = 0,
382                    dataSize="env.dataSize", addressSize="env.addressSize"):
383                super(LoadOp, self).__init__(data, segment,
384                        addr, disp, dataSize, addressSize)
385                self.className = Name
386                self.mnemonic = name
387
388        microopClasses[name] = LoadOp
389
390    defineMicroLoadOp('Ld', 'Data = merge(Data, Mem, dataSize);')
391    defineMicroLoadOp('Ldst', 'Data = merge(Data, Mem, dataSize);', 'StoreCheck')
392    defineMicroLoadOp('Ldfp', 'FpData.uqw = Mem;')
393
394    def defineMicroStoreOp(mnemonic, code, mem_flags=0):
395        global header_output
396        global decoder_output
397        global exec_output
398        global microopClasses
399        Name = mnemonic
400        name = mnemonic.lower()
401
402        # Build up the all register version of this micro op
403        iop = InstObjParams(name, Name, 'X86ISA::LdStOp',
404                {"code": code,
405                 "ea_code": calculateEA,
406                 "mem_flags": mem_flags})
407        header_output += MicroLdStOpDeclare.subst(iop)
408        decoder_output += MicroLdStOpConstructor.subst(iop)
409        exec_output += MicroStoreExecute.subst(iop)
410        exec_output += MicroStoreInitiateAcc.subst(iop)
411        exec_output += MicroStoreCompleteAcc.subst(iop)
412
413        class StoreOp(LdStOp):
414            def __init__(self, data, segment, addr, disp = 0,
415                    dataSize="env.dataSize", addressSize="env.addressSize"):
416                super(StoreOp, self).__init__(data, segment,
417                        addr, disp, dataSize, addressSize)
418                self.className = Name
419                self.mnemonic = name
420
421        microopClasses[name] = StoreOp
422
423    defineMicroStoreOp('St', 'Mem = Data;')
424    defineMicroStoreOp('Stfp', 'Mem = FpData.uqw;')
425    defineMicroStoreOp('Stupd', '''
426            Mem = Data;
427            Base = merge(Base, EA - SegBase, addressSize);
428            ''');
429
430
431    iop = InstObjParams("lea", "Lea", 'X86ISA::LdStOp',
432            {"code": "Data = merge(Data, EA, dataSize);",
433             "ea_code": calculateEA,
434             "mem_flags": 0})
435    header_output += MicroLeaDeclare.subst(iop)
436    decoder_output += MicroLdStOpConstructor.subst(iop)
437    exec_output += MicroLeaExecute.subst(iop)
438
439    class LeaOp(LdStOp):
440        def __init__(self, data, segment, addr, disp = 0,
441                dataSize="env.dataSize", addressSize="env.addressSize"):
442            super(LeaOp, self).__init__(data, segment,
443                    addr, disp, dataSize, addressSize)
444            self.className = "Lea"
445            self.mnemonic = "lea"
446
447    microopClasses["lea"] = LeaOp
448
449
450    iop = InstObjParams("cda", "Cda", 'X86ISA::LdStOp',
451            {"code": '''
452            Addr paddr;
453            fault = xc->translateDataWriteAddr(EA, paddr,
454                dataSize, (1 << segment));
455            ''',
456            "ea_code": calculateEA})
457    header_output += MicroLeaDeclare.subst(iop)
458    decoder_output += MicroLdStOpConstructor.subst(iop)
459    exec_output += MicroLeaExecute.subst(iop)
460
461    class CdaOp(LdStOp):
462        def __init__(self, segment, addr, disp = 0,
463                dataSize="env.dataSize", addressSize="env.addressSize"):
464            super(CdaOp, self).__init__("NUM_INTREGS", segment,
465                    addr, disp, dataSize, addressSize)
466            self.className = "Cda"
467            self.mnemonic = "cda"
468
469    microopClasses["cda"] = CdaOp
470}};
471
472