ldstop.isa revision 4767:5e55d650692e
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        fault = read(xc, EA, Mem, 0);
127        int offset = EA & (dataSize - 1);
128        Mem = bits(Mem, (offset + dataSize) * 8 - 1,  offset * 8);
129
130        if(fault == NoFault)
131        {
132            %(code)s;
133        }
134        if(fault == NoFault)
135        {
136            %(op_wb)s;
137        }
138
139        return fault;
140    }
141}};
142
143def template MicroLoadInitiateAcc {{
144    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc,
145            Trace::InstRecord * traceData) const
146    {
147        Fault fault = NoFault;
148        Addr EA;
149
150        %(op_decl)s;
151        %(op_rd)s;
152        %(ea_code)s;
153        DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
154
155        int offset = EA & (dataSize - 1);
156        fault = read(xc, EA, Mem, offset);
157
158        return fault;
159    }
160}};
161
162def template MicroLoadCompleteAcc {{
163    Fault %(class_name)s::completeAcc(PacketPtr pkt,
164            %(CPU_exec_context)s * xc,
165            Trace::InstRecord * traceData) const
166    {
167        Fault fault = NoFault;
168
169        %(op_decl)s;
170        %(op_rd)s;
171
172        Mem = pkt->get<typeof(Mem)>();
173        int offset = pkt->flags;
174        Mem = bits(Mem, (offset + dataSize) * 8 - 1,  offset * 8);
175        %(code)s;
176
177        if(fault == NoFault)
178        {
179            %(op_wb)s;
180        }
181
182        return fault;
183    }
184}};
185
186// Store templates
187
188def template MicroStoreExecute {{
189    Fault %(class_name)s::execute(%(CPU_exec_context)s * xc,
190            Trace::InstRecord *traceData) const
191    {
192        Fault fault = NoFault;
193
194        Addr EA;
195        %(op_decl)s;
196        %(op_rd)s;
197        %(ea_code)s;
198        DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
199
200        %(code)s;
201
202        if(fault == NoFault)
203        {
204            Mem = Mem << ((EA & (dataSize - 1)) * 8);
205            fault = write(xc, Mem, EA, 0);
206            if(fault == NoFault)
207            {
208                %(op_wb)s;
209            }
210        }
211
212        return fault;
213    }
214}};
215
216def template MicroStoreInitiateAcc {{
217    Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc,
218            Trace::InstRecord * traceData) const
219    {
220        Fault fault = NoFault;
221
222        Addr EA;
223        %(op_decl)s;
224        %(op_rd)s;
225        %(ea_code)s;
226        DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
227
228        %(code)s;
229
230        if(fault == NoFault)
231        {
232            Mem = Mem << ((EA & (dataSize - 1)) * 8);
233            fault = write(xc, Mem, EA, 0);
234            if(fault == NoFault)
235            {
236                %(op_wb)s;
237            }
238        }
239        return fault;
240    }
241}};
242
243def template MicroStoreCompleteAcc {{
244    Fault %(class_name)s::completeAcc(PacketPtr, %(CPU_exec_context)s * xc,
245            Trace::InstRecord * traceData) const
246    {
247        return NoFault;
248    }
249}};
250
251// Common templates
252
253//This delcares the initiateAcc function in memory operations
254def template InitiateAccDeclare {{
255    Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
256}};
257
258//This declares the completeAcc function in memory operations
259def template CompleteAccDeclare {{
260    Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const;
261}};
262
263def template MicroLdStOpDeclare {{
264    class %(class_name)s : public %(base_class)s
265    {
266      protected:
267        void buildMe();
268
269      public:
270        %(class_name)s(ExtMachInst _machInst,
271                const char * instMnem,
272                bool isMicro, bool isDelayed, bool isFirst, bool isLast,
273                uint8_t _scale, RegIndex _index, RegIndex _base,
274                uint64_t _disp, uint8_t _segment,
275                RegIndex _data,
276                uint8_t _dataSize, uint8_t _addressSize);
277
278        %(class_name)s(ExtMachInst _machInst,
279                const char * instMnem,
280                uint8_t _scale, RegIndex _index, RegIndex _base,
281                uint64_t _disp, uint8_t _segment,
282                RegIndex _data,
283                uint8_t _dataSize, uint8_t _addressSize);
284
285        %(BasicExecDeclare)s
286
287        %(InitiateAccDeclare)s
288
289        %(CompleteAccDeclare)s
290    };
291}};
292
293def template MicroLdStOpConstructor {{
294
295    inline void %(class_name)s::buildMe()
296    {
297        %(constructor)s;
298    }
299
300    inline %(class_name)s::%(class_name)s(
301            ExtMachInst machInst, const char * instMnem,
302            uint8_t _scale, RegIndex _index, RegIndex _base,
303            uint64_t _disp, uint8_t _segment,
304            RegIndex _data,
305            uint8_t _dataSize, uint8_t _addressSize) :
306        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
307                false, false, false, false,
308                _scale, _index, _base,
309                _disp, _segment, _data,
310                _dataSize, _addressSize, %(op_class)s)
311    {
312        buildMe();
313    }
314
315    inline %(class_name)s::%(class_name)s(
316            ExtMachInst machInst, const char * instMnem,
317            bool isMicro, bool isDelayed, bool isFirst, bool isLast,
318            uint8_t _scale, RegIndex _index, RegIndex _base,
319            uint64_t _disp, uint8_t _segment,
320            RegIndex _data,
321            uint8_t _dataSize, uint8_t _addressSize) :
322        %(base_class)s(machInst, "%(mnemonic)s", instMnem,
323                isMicro, isDelayed, isFirst, isLast,
324                _scale, _index, _base,
325                _disp, _segment, _data,
326                _dataSize, _addressSize, %(op_class)s)
327    {
328        buildMe();
329    }
330}};
331
332let {{
333    class LdStOp(X86Microop):
334        def __init__(self, data, segment, addr, disp, dataSize):
335            self.data = data
336            [self.scale, self.index, self.base] = addr
337            self.disp = disp
338            self.segment = segment
339            self.dataSize = dataSize
340            self.addressSize = "env.addressSize"
341
342        def getAllocator(self, *microFlags):
343            allocator = '''new %(class_name)s(machInst, mnemonic
344                    %(flags)s, %(scale)s, %(index)s, %(base)s,
345                    %(disp)s, %(segment)s, %(data)s,
346                    %(dataSize)s, %(addressSize)s)''' % {
347                "class_name" : self.className,
348                "flags" : self.microFlagsText(microFlags),
349                "scale" : self.scale, "index" : self.index,
350                "base" : self.base,
351                "disp" : self.disp,
352                "segment" : self.segment, "data" : self.data,
353                "dataSize" : self.dataSize, "addressSize" : self.addressSize}
354            return allocator
355}};
356
357let {{
358
359    # Make these empty strings so that concatenating onto
360    # them will always work.
361    header_output = ""
362    decoder_output = ""
363    exec_output = ""
364
365    calculateEA = "EA = scale * Index + Base + disp;"
366
367    def defineMicroLoadOp(mnemonic, code):
368        global header_output
369        global decoder_output
370        global exec_output
371        global microopClasses
372        Name = mnemonic
373        name = mnemonic.lower()
374
375        # Build up the all register version of this micro op
376        iop = InstObjParams(name, Name, 'X86ISA::LdStOp',
377                {"code": code, "ea_code": calculateEA})
378        header_output += MicroLdStOpDeclare.subst(iop)
379        decoder_output += MicroLdStOpConstructor.subst(iop)
380        exec_output += MicroLoadExecute.subst(iop)
381        exec_output += MicroLoadInitiateAcc.subst(iop)
382        exec_output += MicroLoadCompleteAcc.subst(iop)
383
384        class LoadOp(LdStOp):
385            def __init__(self, data, segment, addr,
386                    disp = 0, dataSize="env.dataSize"):
387                super(LoadOp, self).__init__(data, segment,
388                        addr, disp, dataSize)
389                self.className = Name
390                self.mnemonic = name
391
392        microopClasses[name] = LoadOp
393
394    defineMicroLoadOp('Ld', 'Data = merge(Data, Mem, dataSize);')
395
396    def defineMicroStoreOp(mnemonic, code):
397        global header_output
398        global decoder_output
399        global exec_output
400        global microopClasses
401        Name = mnemonic
402        name = mnemonic.lower()
403
404        # Build up the all register version of this micro op
405        iop = InstObjParams(name, Name, 'X86ISA::LdStOp',
406                {"code": code, "ea_code": calculateEA})
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,
415                    disp = 0, dataSize="env.dataSize"):
416                super(StoreOp, self).__init__(data, segment,
417                        addr, disp, dataSize)
418                self.className = Name
419                self.mnemonic = name
420
421        microopClasses[name] = StoreOp
422
423    defineMicroStoreOp('St', 'Mem = Data;')
424
425    iop = InstObjParams("lea", "Lea", 'X86ISA::LdStOp',
426            {"code": "Data = merge(Data, EA, dataSize);", "ea_code": calculateEA})
427    header_output += MicroLeaDeclare.subst(iop)
428    decoder_output += MicroLdStOpConstructor.subst(iop)
429    exec_output += MicroLeaExecute.subst(iop)
430
431    class LeaOp(LdStOp):
432        def __init__(self, data, segment, addr,
433                disp = 0, dataSize="env.dataSize"):
434            super(LeaOp, self).__init__(data, segment,
435                    addr, disp, dataSize)
436            self.className = "Lea"
437            self.mnemonic = "lea"
438
439    microopClasses["lea"] = LeaOp
440}};
441
442