blockmem.isa revision 3379
16145Snate@binkert.org////////////////////////////////////////////////////////////////////
26145Snate@binkert.org//
36145Snate@binkert.org// Block Memory instructions
46145Snate@binkert.org//
56145Snate@binkert.org
66145Snate@binkert.orgoutput header {{
76145Snate@binkert.org
86145Snate@binkert.org        class BlockMem : public SparcMacroInst
96145Snate@binkert.org        {
106145Snate@binkert.org          protected:
116145Snate@binkert.org
126145Snate@binkert.org            // Constructor
136145Snate@binkert.org            // We make the assumption that all block memory operations
146145Snate@binkert.org            // Will take 8 instructions to execute
156145Snate@binkert.org            BlockMem(const char *mnem,
166145Snate@binkert.org                    ExtMachInst _machInst, OpClass __opClass) :
176145Snate@binkert.org                SparcMacroInst(mnem, _machInst, __opClass, 8)
186145Snate@binkert.org            {}
196145Snate@binkert.org        };
206145Snate@binkert.org
216145Snate@binkert.org        class BlockMemImm : public BlockMem
226145Snate@binkert.org        {
236145Snate@binkert.org          protected:
246145Snate@binkert.org
256145Snate@binkert.org            // Constructor
266145Snate@binkert.org            BlockMemImm(const char *mnem,
276145Snate@binkert.org                    ExtMachInst _machInst, OpClass __opClass) :
286154Snate@binkert.org                BlockMem(mnem, _machInst, __opClass),
296154Snate@binkert.org                imm(sext<13>(SIMM13))
306154Snate@binkert.org            {}
316154Snate@binkert.org
326145Snate@binkert.org            const int32_t imm;
336145Snate@binkert.org        };
346145Snate@binkert.org
356145Snate@binkert.org        class BlockMemMicro : public SparcDelayedMicroInst
366145Snate@binkert.org        {
376145Snate@binkert.org          protected:
386145Snate@binkert.org
396145Snate@binkert.org            // Constructor
406145Snate@binkert.org            BlockMemMicro(const char *mnem, ExtMachInst _machInst,
416145Snate@binkert.org                    OpClass __opClass, int8_t _offset) :
426145Snate@binkert.org                SparcDelayedMicroInst(mnem, _machInst, __opClass),
436145Snate@binkert.org                offset(_offset)
446145Snate@binkert.org            {}
456145Snate@binkert.org
466145Snate@binkert.org            std::string generateDisassembly(Addr pc,
476145Snate@binkert.org                const SymbolTable *symtab) const;
486145Snate@binkert.org
496145Snate@binkert.org            const int8_t offset;
506145Snate@binkert.org        };
516145Snate@binkert.org
526145Snate@binkert.org        class BlockMemImmMicro : public BlockMemMicro
536145Snate@binkert.org        {
546145Snate@binkert.org          protected:
556145Snate@binkert.org
566145Snate@binkert.org            // Constructor
576145Snate@binkert.org            BlockMemImmMicro(const char *mnem, ExtMachInst _machInst,
586145Snate@binkert.org                    OpClass __opClass, int8_t _offset) :
596145Snate@binkert.org                BlockMemMicro(mnem, _machInst, __opClass, _offset),
606145Snate@binkert.org                imm(sext<13>(SIMM13))
616145Snate@binkert.org            {}
626145Snate@binkert.org
636145Snate@binkert.org            std::string generateDisassembly(Addr pc,
646145Snate@binkert.org                const SymbolTable *symtab) const;
656145Snate@binkert.org
666145Snate@binkert.org            const int32_t imm;
676145Snate@binkert.org        };
686145Snate@binkert.org}};
696145Snate@binkert.org
706145Snate@binkert.orgoutput decoder {{
716145Snate@binkert.org        std::string BlockMemMicro::generateDisassembly(Addr pc,
726145Snate@binkert.org                const SymbolTable *symtab) const
736145Snate@binkert.org        {
746145Snate@binkert.org            std::stringstream response;
756145Snate@binkert.org            bool load = flags[IsLoad];
766145Snate@binkert.org            bool save = flags[IsStore];
776145Snate@binkert.org
786145Snate@binkert.org            printMnemonic(response, mnemonic);
796145Snate@binkert.org            if(save)
806145Snate@binkert.org            {
816145Snate@binkert.org                printReg(response, _srcRegIdx[0]);
826145Snate@binkert.org                ccprintf(response, ", ");
836145Snate@binkert.org            }
846145Snate@binkert.org            ccprintf(response, "[ ");
856145Snate@binkert.org            printReg(response, _srcRegIdx[!save ? 0 : 1]);
866145Snate@binkert.org            ccprintf(response, " + ");
876145Snate@binkert.org            printReg(response, _srcRegIdx[!save ? 1 : 2]);
886145Snate@binkert.org            ccprintf(response, " ]");
896145Snate@binkert.org            if(load)
906145Snate@binkert.org            {
916145Snate@binkert.org                ccprintf(response, ", ");
926145Snate@binkert.org                printReg(response, _destRegIdx[0]);
936145Snate@binkert.org            }
946145Snate@binkert.org
956145Snate@binkert.org            return response.str();
966145Snate@binkert.org        }
976145Snate@binkert.org
986145Snate@binkert.org        std::string BlockMemImmMicro::generateDisassembly(Addr pc,
996145Snate@binkert.org                const SymbolTable *symtab) const
1006145Snate@binkert.org        {
1016145Snate@binkert.org            std::stringstream response;
1026145Snate@binkert.org            bool load = flags[IsLoad];
1036145Snate@binkert.org            bool save = flags[IsStore];
1046145Snate@binkert.org
1056145Snate@binkert.org            printMnemonic(response, mnemonic);
1066145Snate@binkert.org            if(save)
1076145Snate@binkert.org            {
1086145Snate@binkert.org                printReg(response, _srcRegIdx[1]);
1096145Snate@binkert.org                ccprintf(response, ", ");
1106145Snate@binkert.org            }
1116145Snate@binkert.org            ccprintf(response, "[ ");
1126145Snate@binkert.org            printReg(response, _srcRegIdx[0]);
1136145Snate@binkert.org            if(imm >= 0)
1146145Snate@binkert.org                ccprintf(response, " + 0x%x ]", imm);
1156145Snate@binkert.org            else
1166145Snate@binkert.org                ccprintf(response, " + -0x%x ]", -imm);
1176145Snate@binkert.org            if(load)
1186145Snate@binkert.org            {
1196145Snate@binkert.org                ccprintf(response, ", ");
1206145Snate@binkert.org                printReg(response, _destRegIdx[0]);
1216145Snate@binkert.org            }
1226145Snate@binkert.org
1236145Snate@binkert.org            return response.str();
1246145Snate@binkert.org        }
1256145Snate@binkert.org
1266145Snate@binkert.org}};
1276145Snate@binkert.org
1286145Snate@binkert.orgdef template LoadStoreExecute {{
1296145Snate@binkert.org        Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
1306145Snate@binkert.org                Trace::InstRecord *traceData) const
1316145Snate@binkert.org        {
1326145Snate@binkert.org            Fault fault = NoFault;
1336145Snate@binkert.org            uint64_t write_result = 0;
1346145Snate@binkert.org            Addr EA;
1356145Snate@binkert.org            %(op_decl)s;
1366145Snate@binkert.org            %(op_rd)s;
1376145Snate@binkert.org            %(priv_check)s;
1386145Snate@binkert.org            %(ea_code)s;
1396145Snate@binkert.org            DPRINTF(Sparc, "The address is 0x%x\n", EA);
1406145Snate@binkert.org            xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, 0);
1416145Snate@binkert.org            %(code)s;
1426145Snate@binkert.org
1436145Snate@binkert.org            if(fault == NoFault)
1446145Snate@binkert.org            {
1456145Snate@binkert.org                xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result);
1466145Snate@binkert.org                //Write the resulting state to the execution context
1476145Snate@binkert.org                %(op_wb)s;
1486145Snate@binkert.org            }
1496145Snate@binkert.org
1506145Snate@binkert.org            return fault;
1516145Snate@binkert.org        }
1526145Snate@binkert.org}};
1536145Snate@binkert.org
1546145Snate@binkert.orgdef template BlockMemDeclare {{
1556145Snate@binkert.org        /**
1566145Snate@binkert.org         * Static instruction class for a block memory operation
1576145Snate@binkert.org         */
1586145Snate@binkert.org        class %(class_name)s : public %(base_class)s
1596145Snate@binkert.org        {
1606145Snate@binkert.org          public:
1616145Snate@binkert.org            //Constructor
1626145Snate@binkert.org            %(class_name)s(ExtMachInst machInst);
1636145Snate@binkert.org
1646145Snate@binkert.org          protected:
1656145Snate@binkert.org            class %(class_name)s_0 : public %(base_class)sMicro
1666145Snate@binkert.org            {
1676145Snate@binkert.org              public:
1686145Snate@binkert.org                //Constructor
1696145Snate@binkert.org                %(class_name)s_0(ExtMachInst machInst);
1706145Snate@binkert.org                %(BasicExecDeclare)s
1716145Snate@binkert.org            };
1726145Snate@binkert.org
1736145Snate@binkert.org            class %(class_name)s_1 : public %(base_class)sMicro
1746145Snate@binkert.org            {
1756145Snate@binkert.org              public:
1766145Snate@binkert.org                //Constructor
1776145Snate@binkert.org                %(class_name)s_1(ExtMachInst machInst);
1786145Snate@binkert.org                %(BasicExecDeclare)s
1796145Snate@binkert.org            };
1806145Snate@binkert.org
1816145Snate@binkert.org            class %(class_name)s_2 : public %(base_class)sMicro
1826145Snate@binkert.org            {
1836145Snate@binkert.org              public:
1846145Snate@binkert.org                //Constructor
1856145Snate@binkert.org                %(class_name)s_2(ExtMachInst machInst);
1866145Snate@binkert.org                %(BasicExecDeclare)s
1876145Snate@binkert.org            };
1886145Snate@binkert.org
1896145Snate@binkert.org            class %(class_name)s_3 : public %(base_class)sMicro
1906145Snate@binkert.org            {
1916145Snate@binkert.org              public:
1926145Snate@binkert.org                //Constructor
1936145Snate@binkert.org                %(class_name)s_3(ExtMachInst machInst);
1946145Snate@binkert.org                %(BasicExecDeclare)s
1956145Snate@binkert.org            };
1966145Snate@binkert.org
1976145Snate@binkert.org            class %(class_name)s_4 : public %(base_class)sMicro
1986145Snate@binkert.org            {
1996145Snate@binkert.org              public:
2006145Snate@binkert.org                //Constructor
2016145Snate@binkert.org                %(class_name)s_4(ExtMachInst machInst);
2026145Snate@binkert.org                %(BasicExecDeclare)s
2036145Snate@binkert.org            };
2046145Snate@binkert.org
2056145Snate@binkert.org            class %(class_name)s_5 : public %(base_class)sMicro
2066145Snate@binkert.org            {
2076145Snate@binkert.org              public:
2086145Snate@binkert.org                //Constructor
2096145Snate@binkert.org                %(class_name)s_5(ExtMachInst machInst);
2106145Snate@binkert.org                %(BasicExecDeclare)s
2116145Snate@binkert.org            };
2126145Snate@binkert.org
2136145Snate@binkert.org            class %(class_name)s_6 : public %(base_class)sMicro
2146145Snate@binkert.org            {
2156145Snate@binkert.org              public:
2166145Snate@binkert.org                //Constructor
2176145Snate@binkert.org                %(class_name)s_6(ExtMachInst machInst);
2186145Snate@binkert.org                %(BasicExecDeclare)s
2196145Snate@binkert.org            };
2206145Snate@binkert.org
2216145Snate@binkert.org            class %(class_name)s_7 : public %(base_class)sMicro
2226145Snate@binkert.org            {
2236145Snate@binkert.org              public:
2246145Snate@binkert.org                //Constructor
2256145Snate@binkert.org                %(class_name)s_7(ExtMachInst machInst);
2266145Snate@binkert.org                %(BasicExecDeclare)s
2276145Snate@binkert.org            };
2286145Snate@binkert.org        };
2296145Snate@binkert.org}};
2306145Snate@binkert.org
2316145Snate@binkert.org// Basic instruction class constructor template.
2326145Snate@binkert.orgdef template BlockMemConstructor {{
2336145Snate@binkert.org        inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
2346145Snate@binkert.org            : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
2356145Snate@binkert.org        {
2366145Snate@binkert.org            %(constructor)s;
2376145Snate@binkert.org            microOps[0] = new %(class_name)s_0(machInst);
2386145Snate@binkert.org            microOps[1] = new %(class_name)s_1(machInst);
2396145Snate@binkert.org            microOps[2] = new %(class_name)s_2(machInst);
2406145Snate@binkert.org            microOps[3] = new %(class_name)s_3(machInst);
2416145Snate@binkert.org            microOps[4] = new %(class_name)s_4(machInst);
2426145Snate@binkert.org            microOps[5] = new %(class_name)s_5(machInst);
2436145Snate@binkert.org            microOps[6] = new %(class_name)s_6(machInst);
2446145Snate@binkert.org            microOps[7] = new %(class_name)s_7(machInst);
2456145Snate@binkert.org        }
2466145Snate@binkert.org}};
2476145Snate@binkert.org
2486145Snate@binkert.orgdef template BlockMemMicroConstructor {{
2496145Snate@binkert.org        inline %(class_name)s::
2506145Snate@binkert.org            %(class_name)s_%(micro_pc)s::
2516145Snate@binkert.org            %(class_name)s_%(micro_pc)s(ExtMachInst machInst) :
2526145Snate@binkert.org                %(base_class)sMicro("%(mnemonic)s[%(micro_pc)s]",
2536145Snate@binkert.org                        machInst, %(op_class)s, %(micro_pc)s * 8)
2546145Snate@binkert.org    {
2556145Snate@binkert.org        %(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