ldstop.isa revision 4867:2de05bc73640
1// Copyright (c) 2007 The Hewlett-Packard Development Company
2// All rights reserved.
3//
4// Redistribution and use of this software in source and binary forms,
5// with or without modification, are permitted provided that the
6// following conditions are met:
7//
8// The software must be used only for Non-Commercial Use which means any
9// use which is NOT directed to receiving any direct monetary
10// compensation for, or commercial advantage from such use.  Illustrative
11// examples of non-commercial use are academic research, personal study,
12// teaching, education and corporate research & development.
13// Illustrative examples of commercial use are distributing products for
14// commercial advantage and providing services using the software for
15// commercial advantage.
16//
17// If you wish to use this software or functionality therein that may be
18// covered by patents for commercial use, please contact:
19//     Director of Intellectual Property Licensing
20//     Office of Strategy and Technology
21//     Hewlett-Packard Company
22//     1501 Page Mill Road
23//     Palo Alto, California  94304
24//
25// Redistributions of source code must retain the above copyright notice,
26// this list of conditions and the following disclaimer.  Redistributions
27// in binary form must reproduce the above copyright notice, this list of
28// conditions and the following disclaimer in the documentation and/or
29// other materials provided with the distribution.  Neither the name of
30// the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
31// contributors may be used to endorse or promote products derived from
32// this software without specific prior written permission.  No right of
33// sublicense is granted herewith.  Derivatives of the software and
34// output created using the software may be prepared, but only for
35// Non-Commercial Uses.  Derivatives of the software may be shared with
36// others provided: (i) the others agree to abide by the list of
37// conditions herein which includes the Non-Commercial Use restrictions;
38// and (ii) such Derivatives of the software include the above copyright
39// notice to acknowledge the contribution from this software where
40// applicable, this list of conditions and the disclaimer below.
41//
42// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
43// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
44// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
45// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
46// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
47// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
48// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
49// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
50// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
51// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
52// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53//
54// Authors: Gabe Black
55
56//////////////////////////////////////////////////////////////////////////
57//
58// LdStOp Microop templates
59//
60//////////////////////////////////////////////////////////////////////////
61
62// LEA template
63
64def template MicroLeaExecute {{
65    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
66          Trace::InstRecord *traceData) const
67    {
68        Fault fault = NoFault;
69        Addr EA;
70
71        %(op_decl)s;
72        %(op_rd)s;
73        %(ea_code)s;
74        DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
75
76        %(code)s;
77        if(fault == NoFault)
78        {
79            %(op_wb)s;
80        }
81
82        return fault;
83    }
84}};
85
86def template MicroLeaDeclare {{
87    class %(class_name)s : public %(base_class)s
88    {
89      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        Twin64_t alignedMem;
127        fault = read(xc, EA, alignedMem, 0);
128        int offset = EA & (dataSize - 1);
129        if(dataSize != 8 || !offset)
130        {
131            Mem = bits(alignedMem.a,
132                    (offset + dataSize) * 8 - 1,  offset * 8);
133        }
134        else
135        {
136            Mem = alignedMem.b << (dataSize - offset) * 8;
137            Mem |= bits(alignedMem.a, dataSize * 8 - 1, offset * 8);
138        }
139
140        if(fault == NoFault)
141        {
142            %(code)s;
143        }
144        if(fault == NoFault)
145        {
146            %(op_wb)s;
147        }
148
149        return fault;
150    }
151}};
152
153def template MicroLoadInitiateAcc {{
154    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc,
155            Trace::InstRecord * traceData) const
156    {
157        Fault fault = NoFault;
158        Addr EA;
159
160        %(op_decl)s;
161        %(op_rd)s;
162        %(ea_code)s;
163        DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
164
165        int offset = EA & (dataSize - 1);
166        Twin64_t alignedMem;
167        fault = read(xc, EA, alignedMem, offset);
168
169        return fault;
170    }
171}};
172
173def template MicroLoadCompleteAcc {{
174    Fault %(class_name)s::completeAcc(PacketPtr pkt,
175            %(CPU_exec_context)s * xc,
176            Trace::InstRecord * traceData) const
177    {
178        Fault fault = NoFault;
179
180        %(op_decl)s;
181        %(op_rd)s;
182
183        Twin64_t alignedMem = pkt->get<Twin64_t>();
184        int offset = pkt->req->getFlags();
185        if(dataSize != 8 || !offset)
186        {
187            Mem = bits(alignedMem.a,
188                    (offset + dataSize) * 8 - 1,  offset * 8);
189        }
190        else
191        {
192            Mem = alignedMem.b << (dataSize - offset) * 8;
193            Mem |= bits(alignedMem.a, dataSize * 8 - 1, offset * 8);
194        }
195        %(code)s;
196
197        if(fault == NoFault)
198        {
199            %(op_wb)s;
200        }
201
202        return fault;
203    }
204}};
205
206// Store templates
207
208def template MicroStoreExecute {{
209    Fault %(class_name)s::execute(%(CPU_exec_context)s * xc,
210            Trace::InstRecord *traceData) const
211    {
212        Fault fault = NoFault;
213
214        Addr EA;
215        %(op_decl)s;
216        %(op_rd)s;
217        %(ea_code)s;
218        DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
219
220        %(code)s;
221
222        if(fault == NoFault)
223        {
224            int offset = EA & (dataSize - 1);
225
226            Twin64_t alignedMem;
227            alignedMem.a = Mem << (offset * 8);
228            alignedMem.b =
229                bits(Mem, dataSize * 8 - 1, (dataSize - offset) * 8);
230
231            fault = write(xc, alignedMem, EA, 0);
232            if(fault == NoFault)
233            {
234                %(op_wb)s;
235            }
236        }
237
238        return fault;
239    }
240}};
241
242def template MicroStoreInitiateAcc {{
243    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc,
244            Trace::InstRecord * traceData) const
245    {
246        Fault fault = NoFault;
247
248        Addr EA;
249        %(op_decl)s;
250        %(op_rd)s;
251        %(ea_code)s;
252        DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
253
254        %(code)s;
255
256        if(fault == NoFault)
257        {
258            int offset = EA & (dataSize - 1);
259
260            Twin64_t alignedMem;
261            alignedMem.a = Mem << (offset * 8);
262            alignedMem.b =
263                bits(Mem, dataSize * 8 - 1, (dataSize - offset) * 8);
264
265            fault = write(xc, alignedMem, EA, 0);
266            if(fault == NoFault)
267            {
268                %(op_wb)s;
269            }
270        }
271        return fault;
272    }
273}};
274
275def template MicroStoreCompleteAcc {{
276    Fault %(class_name)s::completeAcc(PacketPtr, %(CPU_exec_context)s * xc,
277            Trace::InstRecord * traceData) const
278    {
279        return NoFault;
280    }
281}};
282
283// Common templates
284
285//This delcares the initiateAcc function in memory operations
286def template InitiateAccDeclare {{
287    Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
288}};
289
290//This declares the completeAcc function in memory operations
291def template CompleteAccDeclare {{
292    Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const;
293}};
294
295def template MicroLdStOpDeclare {{
296    class %(class_name)s : public %(base_class)s
297    {
298      protected:
299        void buildMe();
300
301      public:
302        %(class_name)s(ExtMachInst _machInst,
303                const char * instMnem,
304                bool isMicro, bool isDelayed, bool isFirst, bool isLast,
305                uint8_t _scale, RegIndex _index, RegIndex _base,
306                uint64_t _disp, uint8_t _segment,
307                RegIndex _data,
308                uint8_t _dataSize, uint8_t _addressSize);
309
310        %(class_name)s(ExtMachInst _machInst,
311                const char * instMnem,
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
317        %(BasicExecDeclare)s
318
319        %(InitiateAccDeclare)s
320
321        %(CompleteAccDeclare)s
322    };
323}};
324
325def template MicroLdStOpConstructor {{
326
327    inline void %(class_name)s::buildMe()
328    {
329        %(constructor)s;
330    }
331
332    inline %(class_name)s::%(class_name)s(
333            ExtMachInst machInst, const char * instMnem,
334            uint8_t _scale, RegIndex _index, RegIndex _base,
335            uint64_t _disp, uint8_t _segment,
336            RegIndex _data,
337            uint8_t _dataSize, uint8_t _addressSize) :
338        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
339                false, false, false, false,
340                _scale, _index, _base,
341                _disp, _segment, _data,
342                _dataSize, _addressSize, %(op_class)s)
343    {
344        buildMe();
345    }
346
347    inline %(class_name)s::%(class_name)s(
348            ExtMachInst machInst, const char * instMnem,
349            bool isMicro, bool isDelayed, bool isFirst, bool isLast,
350            uint8_t _scale, RegIndex _index, RegIndex _base,
351            uint64_t _disp, uint8_t _segment,
352            RegIndex _data,
353            uint8_t _dataSize, uint8_t _addressSize) :
354        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
355                isMicro, isDelayed, isFirst, isLast,
356                _scale, _index, _base,
357                _disp, _segment, _data,
358                _dataSize, _addressSize, %(op_class)s)
359    {
360        buildMe();
361    }
362}};
363
364let {{
365    class LdStOp(X86Microop):
366        def __init__(self, data, segment, addr, disp, dataSize):
367            self.data = data
368            [self.scale, self.index, self.base] = addr
369            self.disp = disp
370            self.segment = segment
371            self.dataSize = dataSize
372            self.addressSize = "env.addressSize"
373
374        def getAllocator(self, *microFlags):
375            allocator = '''new %(class_name)s(machInst, mnemonic
376                    %(flags)s, %(scale)s, %(index)s, %(base)s,
377                    %(disp)s, %(segment)s, %(data)s,
378                    %(dataSize)s, %(addressSize)s)''' % {
379                "class_name" : self.className,
380                "flags" : self.microFlagsText(microFlags),
381                "scale" : self.scale, "index" : self.index,
382                "base" : self.base,
383                "disp" : self.disp,
384                "segment" : self.segment, "data" : self.data,
385                "dataSize" : self.dataSize, "addressSize" : self.addressSize}
386            return allocator
387}};
388
389let {{
390
391    # Make these empty strings so that concatenating onto
392    # them will always work.
393    header_output = ""
394    decoder_output = ""
395    exec_output = ""
396
397    calculateEA = "EA = SegBase + scale * Index + Base + disp;"
398
399    def defineMicroLoadOp(mnemonic, code):
400        global header_output
401        global decoder_output
402        global exec_output
403        global microopClasses
404        Name = mnemonic
405        name = mnemonic.lower()
406
407        # Build up the all register version of this micro op
408        iop = InstObjParams(name, Name, 'X86ISA::LdStOp',
409                {"code": code, "ea_code": calculateEA})
410        header_output += MicroLdStOpDeclare.subst(iop)
411        decoder_output += MicroLdStOpConstructor.subst(iop)
412        exec_output += MicroLoadExecute.subst(iop)
413        exec_output += MicroLoadInitiateAcc.subst(iop)
414        exec_output += MicroLoadCompleteAcc.subst(iop)
415
416        class LoadOp(LdStOp):
417            def __init__(self, data, segment, addr,
418                    disp = 0, dataSize="env.dataSize"):
419                super(LoadOp, self).__init__(data, segment,
420                        addr, disp, dataSize)
421                self.className = Name
422                self.mnemonic = name
423
424        microopClasses[name] = LoadOp
425
426    defineMicroLoadOp('Ld', 'Data = merge(Data, Mem, dataSize);')
427
428    def defineMicroStoreOp(mnemonic, code):
429        global header_output
430        global decoder_output
431        global exec_output
432        global microopClasses
433        Name = mnemonic
434        name = mnemonic.lower()
435
436        # Build up the all register version of this micro op
437        iop = InstObjParams(name, Name, 'X86ISA::LdStOp',
438                {"code": code, "ea_code": calculateEA})
439        header_output += MicroLdStOpDeclare.subst(iop)
440        decoder_output += MicroLdStOpConstructor.subst(iop)
441        exec_output += MicroStoreExecute.subst(iop)
442        exec_output += MicroStoreInitiateAcc.subst(iop)
443        exec_output += MicroStoreCompleteAcc.subst(iop)
444
445        class StoreOp(LdStOp):
446            def __init__(self, data, segment, addr,
447                    disp = 0, dataSize="env.dataSize"):
448                super(StoreOp, self).__init__(data, segment,
449                        addr, disp, dataSize)
450                self.className = Name
451                self.mnemonic = name
452
453        microopClasses[name] = StoreOp
454
455    defineMicroStoreOp('St', 'Mem = Data;')
456
457    iop = InstObjParams("lea", "Lea", 'X86ISA::LdStOp',
458            {"code": "Data = merge(Data, EA, dataSize);", "ea_code": calculateEA})
459    header_output += MicroLeaDeclare.subst(iop)
460    decoder_output += MicroLdStOpConstructor.subst(iop)
461    exec_output += MicroLeaExecute.subst(iop)
462
463    class LeaOp(LdStOp):
464        def __init__(self, data, segment, addr,
465                disp = 0, dataSize="env.dataSize"):
466            super(LeaOp, self).__init__(data, segment,
467                    addr, disp, dataSize)
468            self.className = "Lea"
469            self.mnemonic = "lea"
470
471    microopClasses["lea"] = LeaOp
472}};
473
474