blob: 94acf41d293304aa00371cd373d62f5100fcf44a [file] [log] [blame]
// -*- mode:c++ -*-
// Copyright (c) 2010-2014 ARM Limited
// All rights reserved
//
// The license below extends only to copyright in the software and shall
// not be construed as granting a license to any other intellectual
// property including but not limited to intellectual property relating
// to a hardware implementation of the functionality of the software
// licensed hereunder. You may use the software subject to the license
// terms below provided that you ensure that this notice is replicated
// unmodified and in its entirety in all distributions of the software,
// modified or unmodified, in source code or in binary form.
//
// Copyright (c) 2007-2008 The Florida State University
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met: redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer;
// redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution;
// neither the name of the copyright holders nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
////////////////////////////////////////////////////////////////////
//
// Load/store microops
//
let {{
microLdrUopCode = "IWRa = cSwap(Mem_uw, ((CPSR)Cpsr).e);"
microLdrUopIop = ArmInstObjParams('ldr_uop', 'MicroLdrUop', 'MicroMemOp',
{ 'memacc_code' : microLdrUopCode,
'ea_code' : 'EA = URb + (up ? imm : -imm);',
'predicate_test' : predicateTest },
['IsMicroop'])
microLdr2UopCode = '''
uint64_t data = Mem_ud;
Dest = cSwap((uint32_t) data, ((CPSR)Cpsr).e);
IWDest2 = cSwap((uint32_t) (data >> 32),
((CPSR)Cpsr).e);
'''
microLdr2UopIop = ArmInstObjParams('ldr2_uop', 'MicroLdr2Uop',
'MicroMemPairOp',
{ 'memacc_code' : microLdr2UopCode,
'ea_code' : 'EA = URb + (up ? imm : -imm);',
'predicate_test' : predicateTest },
['IsMicroop'])
microLdrFpUopCode = "Fa_uw = cSwap(Mem_uw, ((CPSR)Cpsr).e);"
microLdrFpUopIop = ArmInstObjParams('ldrfp_uop', 'MicroLdrFpUop',
'MicroMemOp',
{ 'memacc_code' : microLdrFpUopCode,
'ea_code' : vfpEnabledCheckCode +
'EA = URb + (up ? imm : -imm);',
'predicate_test': predicateTest },
['IsMicroop'])
microLdrDBFpUopCode = "Fa_uw = cSwap(Mem_uw, ((CPSR)Cpsr).e);"
microLdrDBFpUopIop = ArmInstObjParams('ldrfp_uop', 'MicroLdrDBFpUop',
'MicroMemOp',
{ 'memacc_code' : microLdrFpUopCode,
'ea_code' : vfpEnabledCheckCode + '''
EA = URb + (up ? imm : -imm) + (((CPSR)Cpsr).e ? 4 : 0);
''',
'predicate_test' : predicateTest },
['IsMicroop'])
microLdrDTFpUopCode = "Fa_uw = cSwap(Mem_uw, ((CPSR)Cpsr).e);"
microLdrDTFpUopIop = ArmInstObjParams('ldrfp_uop', 'MicroLdrDTFpUop',
'MicroMemOp',
{ 'memacc_code' : microLdrFpUopCode,
'ea_code' : vfpEnabledCheckCode + '''
EA = URb + (up ? imm : -imm) - (((CPSR)Cpsr).e ? 4 : 0);
''',
'predicate_test': predicateTest },
['IsMicroop'])
microRetUopCode = '''
CPSR old_cpsr = Cpsr;
SCTLR sctlr = Sctlr;
CPSR new_cpsr =
cpsrWriteByInstr(old_cpsr, Spsr, Scr, Nsacr, 0xF, true,
sctlr.nmfi, xc->tcBase());
Cpsr = ~CondCodesMask & new_cpsr;
CondCodesNZ = new_cpsr.nz;
CondCodesC = new_cpsr.c;
CondCodesV = new_cpsr.v;
CondCodesGE = new_cpsr.ge;
IWNPC = cSwap(%s, old_cpsr.e) | ((Spsr & 0x20) ? 1 : 0);
NextItState = ((((CPSR)Spsr).it2 << 2) & 0xFC)
| (((CPSR)Spsr).it1 & 0x3);
SevMailbox = 1;
'''
microLdrRetUopIop = ArmInstObjParams('ldr_ret_uop', 'MicroLdrRetUop',
'MicroMemOp',
{ 'memacc_code' : microRetUopCode % 'Mem_uw',
'ea_code' : 'EA = URb + (up ? imm : -imm);',
'predicate_test' : condPredicateTest },
['IsMicroop','IsNonSpeculative',
'IsSerializeAfter', 'IsSquashAfter'])
microStrUopCode = "Mem = cSwap(URa_uw, ((CPSR)Cpsr).e);"
microStrUopIop = ArmInstObjParams('str_uop', 'MicroStrUop', 'MicroMemOp',
{ 'memacc_code' : microStrUopCode,
'postacc_code' : "",
'ea_code' : 'EA = URb + (up ? imm : -imm);',
'predicate_test' : predicateTest },
['IsMicroop'])
microStrFpUopCode = "Mem = cSwap(Fa_uw, ((CPSR)Cpsr).e);"
microStrFpUopIop = ArmInstObjParams('strfp_uop', 'MicroStrFpUop',
'MicroMemOp',
{ 'memacc_code' : microStrFpUopCode,
'postacc_code' : "",
'ea_code' : vfpEnabledCheckCode +
'EA = URb + (up ? imm : -imm);',
'predicate_test' : predicateTest },
['IsMicroop'])
microStrDBFpUopCode = "Mem = cSwap(Fa_uw, ((CPSR)Cpsr).e);"
microStrDBFpUopIop = ArmInstObjParams('strfp_uop', 'MicroStrDBFpUop',
'MicroMemOp',
{ 'memacc_code' : microStrFpUopCode,
'postacc_code' : "",
'ea_code': vfpEnabledCheckCode + '''
EA = URb + (up ? imm : -imm) + (((CPSR)Cpsr).e ? 4 : 0);
''',
'predicate_test' : predicateTest },
['IsMicroop'])
microStrDTFpUopCode = "Mem = cSwap(Fa_uw, ((CPSR)Cpsr).e);"
microStrDTFpUopIop = ArmInstObjParams('strfp_uop', 'MicroStrDTFpUop',
'MicroMemOp',
{ 'memacc_code' : microStrFpUopCode,
'postacc_code' : "",
'ea_code' : vfpEnabledCheckCode + '''
EA = URb + (up ? imm : -imm) - (((CPSR)Cpsr).e ? 4 : 0);
''',
'predicate_test' : predicateTest },
['IsMicroop'])
header_output = decoder_output = exec_output = ''
loadIops = (microLdrUopIop, microLdrRetUopIop,
microLdrFpUopIop, microLdrDBFpUopIop, microLdrDTFpUopIop)
storeIops = (microStrUopIop, microStrFpUopIop,
microStrDBFpUopIop, microStrDTFpUopIop)
for iop in loadIops + storeIops:
header_output += MicroMemDeclare.subst(iop)
decoder_output += MicroMemConstructor.subst(iop)
for iop in loadIops:
exec_output += LoadExecute.subst(iop) + \
LoadInitiateAcc.subst(iop) + \
LoadCompleteAcc.subst(iop)
for iop in storeIops:
exec_output += StoreExecute.subst(iop) + \
StoreInitiateAcc.subst(iop) + \
StoreCompleteAcc.subst(iop)
header_output += MicroMemPairDeclare.subst(microLdr2UopIop)
decoder_output += MicroMemPairConstructor.subst(microLdr2UopIop)
exec_output += LoadExecute.subst(microLdr2UopIop) + \
LoadInitiateAcc.subst(microLdr2UopIop) + \
LoadCompleteAcc.subst(microLdr2UopIop)
}};
let {{
exec_output = header_output = ''
eaCode = 'EA = XURa + imm;'
for size in (1, 2, 3, 4, 6, 8, 12, 16):
# Set up the memory access.
regs = (size + 3) // 4
subst = { "size" : size, "regs" : regs }
memDecl = '''
union MemUnion
{
uint8_t bytes[%(size)d];
Element elements[%(size)d / sizeof(Element)];
uint32_t floatRegBits[%(regs)d];
};
''' % subst
# Do endian conversion for all the elements.
convCode = '''
const unsigned eCount = sizeof(memUnion.elements) /
sizeof(memUnion.elements[0]);
if (((CPSR)Cpsr).e) {
for (unsigned i = 0; i < eCount; i++) {
memUnion.elements[i] = letobe(memUnion.elements[i]);
}
} else {
for (unsigned i = 0; i < eCount; i++) {
memUnion.elements[i] = memUnion.elements[i];
}
}
'''
# Offload everything into registers
regSetCode = ''
for reg in range(regs):
mask = ''
if reg == regs - 1:
mask = ' & mask(%d)' % (32 - 8 * (regs * 4 - size))
regSetCode += '''
FpDestP%(reg)d_uw = letoh(memUnion.floatRegBits[%(reg)d])%(mask)s;
''' % { "reg" : reg, "mask" : mask }
# Pull everything in from registers
regGetCode = ''
for reg in range(regs):
regGetCode += '''
memUnion.floatRegBits[%(reg)d] = htole(FpDestP%(reg)d_uw);
''' % { "reg" : reg }
loadMemAccCode = convCode + regSetCode
storeMemAccCode = regGetCode + convCode
loadIop = ArmInstObjParams('ldrneon%(size)d_uop' % subst,
'MicroLdrNeon%(size)dUop' % subst, 'MicroNeonMemOp',
{ 'mem_decl' : memDecl,
'size' : size,
'memacc_code' : loadMemAccCode,
'ea_code' : simdEnabledCheckCode + eaCode,
'predicate_test' : predicateTest },
[ 'IsMicroop', 'IsLoad' ])
storeIop = ArmInstObjParams('strneon%(size)d_uop' % subst,
'MicroStrNeon%(size)dUop' % subst, 'MicroNeonMemOp',
{ 'mem_decl' : memDecl,
'size' : size,
'memacc_code' : storeMemAccCode,
'ea_code' : simdEnabledCheckCode + eaCode,
'predicate_test' : predicateTest },
[ 'IsMicroop', 'IsStore' ])
exec_output += NeonLoadExecute.subst(loadIop) + \
NeonLoadInitiateAcc.subst(loadIop) + \
NeonLoadCompleteAcc.subst(loadIop) + \
NeonStoreExecute.subst(storeIop) + \
NeonStoreInitiateAcc.subst(storeIop) + \
NeonStoreCompleteAcc.subst(storeIop)
header_output += MicroNeonMemDeclare.subst(loadIop) + \
MicroNeonMemDeclare.subst(storeIop)
}};
let {{
exec_output = ''
for eSize, type in (1, 'uint8_t'), \
(2, 'uint16_t'), \
(4, 'uint32_t'), \
(8, 'uint64_t'):
size = eSize
# An instruction handles no more than 16 bytes and no more than
# 4 elements, or the number of elements needed to fill 8 or 16 bytes.
sizes = set((16, 8))
for count in 1, 2, 3, 4:
size = count * eSize
if size <= 16:
sizes.add(size)
for size in sizes:
substDict = {
"class_name" : "MicroLdrNeon%dUop" % size,
"targs" : type
}
exec_output += MicroNeonMemExecDeclare.subst(substDict)
substDict["class_name"] = "MicroStrNeon%dUop" % size
exec_output += MicroNeonMemExecDeclare.subst(substDict)
size += eSize
}};
////////////////////////////////////////////////////////////////////
//
// Neon (de)interlacing microops
//
let {{
header_output = exec_output = ''
for dRegs in (2, 3, 4):
loadConv = ''
unloadConv = ''
for dReg in range(dRegs):
loadConv += '''
conv1.cRegs[%(sReg0)d] = htole(FpOp1P%(sReg0)d_uw);
conv1.cRegs[%(sReg1)d] = htole(FpOp1P%(sReg1)d_uw);
''' % { "sReg0" : (dReg * 2), "sReg1" : (dReg * 2 + 1) }
unloadConv += '''
FpDestS%(dReg)dP0_uw = letoh(conv2.cRegs[2 * %(dReg)d + 0]);
FpDestS%(dReg)dP1_uw = letoh(conv2.cRegs[2 * %(dReg)d + 1]);
''' % { "dReg" : dReg }
microDeintNeonCode = '''
const unsigned dRegs = %(dRegs)d;
const unsigned regs = 2 * dRegs;
const unsigned perDReg =
(2 * sizeof(uint32_t)) / sizeof(Element);
union convStruct
{
uint32_t cRegs[regs];
Element elements[dRegs * perDReg];
} conv1, conv2;
%(loadConv)s
unsigned srcElem = 0;
for (unsigned destOffset = 0;
destOffset < perDReg; destOffset++) {
for (unsigned dReg = 0; dReg < dRegs; dReg++) {
conv2.elements[dReg * perDReg + destOffset] =
conv1.elements[srcElem++];
}
}
%(unloadConv)s
''' % { "dRegs" : dRegs,
"loadConv" : loadConv,
"unloadConv" : unloadConv }
microDeintNeonIop = \
ArmInstObjParams('deintneon%duop' % (dRegs * 2),
'MicroDeintNeon%dUop' % (dRegs * 2),
'MicroNeonMixOp',
{ 'predicate_test': predicateTest,
'code' : microDeintNeonCode },
['IsMicroop'])
header_output += MicroNeonMixDeclare.subst(microDeintNeonIop)
exec_output += MicroNeonMixExecute.subst(microDeintNeonIop)
loadConv = ''
unloadConv = ''
for dReg in range(dRegs):
loadConv += '''
conv1.cRegs[2 * %(dReg)d + 0] = htole(FpOp1S%(dReg)dP0_uw);
conv1.cRegs[2 * %(dReg)d + 1] = htole(FpOp1S%(dReg)dP1_uw);
''' % { "dReg" : dReg }
unloadConv += '''
FpDestP%(sReg0)d_uw = letoh(conv2.cRegs[%(sReg0)d]);
FpDestP%(sReg1)d_uw = letoh(conv2.cRegs[%(sReg1)d]);
''' % { "sReg0" : (dReg * 2), "sReg1" : (dReg * 2 + 1) }
microInterNeonCode = '''
const unsigned dRegs = %(dRegs)d;
const unsigned regs = 2 * dRegs;
const unsigned perDReg =
(2 * sizeof(uint32_t)) / sizeof(Element);
union convStruct
{
uint32_t cRegs[regs];
Element elements[dRegs * perDReg];
} conv1, conv2;
%(loadConv)s
unsigned destElem = 0;
for (unsigned srcOffset = 0;
srcOffset < perDReg; srcOffset++) {
for (unsigned dReg = 0; dReg < dRegs; dReg++) {
conv2.elements[destElem++] =
conv1.elements[dReg * perDReg + srcOffset];
}
}
%(unloadConv)s
''' % { "dRegs" : dRegs,
"loadConv" : loadConv,
"unloadConv" : unloadConv }
microInterNeonIop = \
ArmInstObjParams('interneon%duop' % (dRegs * 2),
'MicroInterNeon%dUop' % (dRegs * 2),
'MicroNeonMixOp',
{ 'predicate_test': predicateTest,
'code' : microInterNeonCode },
['IsMicroop'])
header_output += MicroNeonMixDeclare.subst(microInterNeonIop)
exec_output += MicroNeonMixExecute.subst(microInterNeonIop)
}};
let {{
exec_output = ''
for type in ('uint8_t', 'uint16_t', 'uint32_t', 'uint64_t'):
for dRegs in (2, 3, 4):
Name = "MicroDeintNeon%dUop" % (dRegs * 2)
substDict = { "class_name" : Name, "targs" : type }
exec_output += MicroNeonExecDeclare.subst(substDict)
Name = "MicroInterNeon%dUop" % (dRegs * 2)
substDict = { "class_name" : Name, "targs" : type }
exec_output += MicroNeonExecDeclare.subst(substDict)
}};
////////////////////////////////////////////////////////////////////
//
// Neon microops to pack/unpack a single lane
//
let {{
header_output = exec_output = ''
for sRegs in 1, 2:
baseLoadRegs = ''
for reg in range(sRegs):
baseLoadRegs += '''
sourceRegs.fRegs[%(reg0)d] = htole(FpOp1P%(reg0)d_uw);
sourceRegs.fRegs[%(reg1)d] = htole(FpOp1P%(reg1)d_uw);
''' % { "reg0" : (2 * reg + 0),
"reg1" : (2 * reg + 1) }
for dRegs in range(sRegs, 5):
unloadRegs = ''
loadRegs = baseLoadRegs
for reg in range(dRegs):
loadRegs += '''
destRegs[%(reg)d].fRegs[0] = htole(FpDestS%(reg)dP0_uw);
destRegs[%(reg)d].fRegs[1] = htole(FpDestS%(reg)dP1_uw);
''' % { "reg" : reg }
unloadRegs += '''
FpDestS%(reg)dP0_uw = letoh(destRegs[%(reg)d].fRegs[0]);
FpDestS%(reg)dP1_uw = letoh(destRegs[%(reg)d].fRegs[1]);
''' % { "reg" : reg }
microUnpackNeonCode = '''
const unsigned perDReg = (2 * sizeof(uint32_t)) / sizeof(Element);
union SourceRegs
{
uint32_t fRegs[2 * %(sRegs)d];
Element elements[%(sRegs)d * perDReg];
} sourceRegs;
union DestReg
{
uint32_t fRegs[2];
Element elements[perDReg];
} destRegs[%(dRegs)d];
%(loadRegs)s
for (unsigned i = 0; i < %(dRegs)d; i++) {
destRegs[i].elements[lane] = sourceRegs.elements[i];
}
%(unloadRegs)s
''' % { "sRegs" : sRegs, "dRegs" : dRegs,
"loadRegs" : loadRegs, "unloadRegs" : unloadRegs }
microUnpackNeonIop = ArmInstObjParams(
'unpackneon%dto%duop' % (sRegs * 2, dRegs * 2),
'MicroUnpackNeon%dto%dUop' % (sRegs * 2, dRegs * 2),
'MicroNeonMixLaneOp',
{ 'predicate_test' : predicateTest,
'code' : microUnpackNeonCode },
['IsMicroop'])
header_output += MicroNeonMixLaneDeclare.subst(microUnpackNeonIop)
exec_output += MicroNeonMixExecute.subst(microUnpackNeonIop)
for sRegs in 1, 2:
loadRegs = ''
for reg in range(sRegs):
loadRegs += '''
sourceRegs.fRegs[%(reg0)d] = htole(FpOp1P%(reg0)d_uw);
sourceRegs.fRegs[%(reg1)d] = htole(FpOp1P%(reg1)d_uw);
''' % { "reg0" : (2 * reg + 0),
"reg1" : (2 * reg + 1) }
for dRegs in range(sRegs, 5):
unloadRegs = ''
for reg in range(dRegs):
unloadRegs += '''
FpDestS%(reg)dP0_uw = letoh(destRegs[%(reg)d].fRegs[0]);
FpDestS%(reg)dP1_uw = letoh(destRegs[%(reg)d].fRegs[1]);
''' % { "reg" : reg }
microUnpackAllNeonCode = '''
const unsigned perDReg = (2 * sizeof(uint32_t)) / sizeof(Element);
union SourceRegs
{
uint32_t fRegs[2 * %(sRegs)d];
Element elements[%(sRegs)d * perDReg];
} sourceRegs;
union DestReg
{
uint32_t fRegs[2];
Element elements[perDReg];
} destRegs[%(dRegs)d];
%(loadRegs)s
for (unsigned i = 0; i < %(dRegs)d; i++) {
for (unsigned j = 0; j < perDReg; j++)
destRegs[i].elements[j] = sourceRegs.elements[i];
}
%(unloadRegs)s
''' % { "sRegs" : sRegs, "dRegs" : dRegs,
"loadRegs" : loadRegs, "unloadRegs" : unloadRegs }
microUnpackAllNeonIop = ArmInstObjParams(
'unpackallneon%dto%duop' % (sRegs * 2, dRegs * 2),
'MicroUnpackAllNeon%dto%dUop' % (sRegs * 2, dRegs * 2),
'MicroNeonMixOp',
{ 'predicate_test' : predicateTest,
'code' : microUnpackAllNeonCode },
['IsMicroop'])
header_output += MicroNeonMixDeclare.subst(microUnpackAllNeonIop)
exec_output += MicroNeonMixExecute.subst(microUnpackAllNeonIop)
for dRegs in 1, 2:
unloadRegs = ''
for reg in range(dRegs):
unloadRegs += '''
FpDestP%(reg0)d_uw = letoh(destRegs.fRegs[%(reg0)d]);
FpDestP%(reg1)d_uw = letoh(destRegs.fRegs[%(reg1)d]);
''' % { "reg0" : (2 * reg + 0),
"reg1" : (2 * reg + 1) }
for sRegs in range(dRegs, 5):
loadRegs = ''
for reg in range(sRegs):
loadRegs += '''
sourceRegs[%(reg)d].fRegs[0] = htole(FpOp1S%(reg)dP0_uw);
sourceRegs[%(reg)d].fRegs[1] = htole(FpOp1S%(reg)dP1_uw);
''' % { "reg" : reg }
microPackNeonCode = '''
const unsigned perDReg =
(2 * sizeof(uint32_t)) / sizeof(Element);
union SourceReg
{
uint32_t fRegs[2];
Element elements[perDReg];
} sourceRegs[%(sRegs)d];
union DestRegs
{
uint32_t fRegs[2 * %(dRegs)d];
Element elements[%(dRegs)d * perDReg];
} destRegs;
%(loadRegs)s
for (unsigned i = 0; i < %(sRegs)d; i++) {
destRegs.elements[i] = sourceRegs[i].elements[lane];
}
for (unsigned i = %(sRegs)d; i < %(dRegs)d * perDReg; ++i) {
destRegs.elements[i] = 0;
}
%(unloadRegs)s
''' % { "sRegs" : sRegs, "dRegs" : dRegs,
"loadRegs" : loadRegs, "unloadRegs" : unloadRegs }
microPackNeonIop = ArmInstObjParams(
'packneon%dto%duop' % (sRegs * 2, dRegs * 2),
'MicroPackNeon%dto%dUop' % (sRegs * 2, dRegs * 2),
'MicroNeonMixLaneOp',
{ 'predicate_test': predicateTest,
'code' : microPackNeonCode },
['IsMicroop'])
header_output += MicroNeonMixLaneDeclare.subst(microPackNeonIop)
exec_output += MicroNeonMixExecute.subst(microPackNeonIop)
}};
let {{
exec_output = ''
for typeSize in (8, 16, 32):
for sRegs in 1, 2:
for dRegs in range(sRegs, min(sRegs * 64 // typeSize + 1, 5)):
for format in ("MicroUnpackNeon%(sRegs)dto%(dRegs)dUop",
"MicroUnpackAllNeon%(sRegs)dto%(dRegs)dUop",
"MicroPackNeon%(dRegs)dto%(sRegs)dUop"):
Name = format % { "sRegs" : sRegs * 2,
"dRegs" : dRegs * 2 }
substDict = { "class_name" : Name,
"targs" : "uint%d_t" % typeSize }
exec_output += MicroNeonExecDeclare.subst(substDict)
}};
////////////////////////////////////////////////////////////////////
//
// Integer = Integer op Immediate microops
//
let {{
microAddiUopIop = ArmInstObjParams('addi_uop', 'MicroAddiUop',
'MicroIntImmOp',
{'code': 'URa = URb + imm;',
'predicate_test': predicateTest},
['IsMicroop'])
microAddUopCode = '''
URa = URb + shift_rm_imm(URc, shiftAmt, shiftType, OptShiftRmCondCodesC);
'''
microAddXiUopIop = ArmInstObjParams('addxi_uop', 'MicroAddXiUop',
'MicroIntImmXOp',
'XURa = XURb + imm;',
['IsMicroop'])
microAddXiSpAlignUopIop = ArmInstObjParams('addxi_uop',
'MicroAddXiSpAlignUop', 'MicroIntImmXOp', '''
if (isSP((IntRegIndex) urb) && bits(XURb, 3, 0) &&
SPAlignmentCheckEnabled(xc->tcBase())) {
return std::make_shared<SPAlignmentFault>();
}
XURa = XURb + imm;
''', ['IsMicroop'])
microAddXERegUopIop = ArmInstObjParams('addxr_uop',
'MicroAddXERegUop', 'MicroIntRegXOp',
'XURa = XURb + extendReg64(XURc, type, shiftAmt, 64);',
['IsMicroop'])
microAddUopIop = ArmInstObjParams('add_uop', 'MicroAddUop',
'MicroIntRegOp',
{ 'code' : microAddUopCode,
'predicate_test': pickPredicate(microAddUopCode)},
['IsMicroop'])
microSubiUopIop = ArmInstObjParams('subi_uop', 'MicroSubiUop',
'MicroIntImmOp',
{ 'code' : 'URa = URb - imm;',
'predicate_test' : predicateTest},
['IsMicroop'])
microSubXiUopIop = ArmInstObjParams('subxi_uop', 'MicroSubXiUop',
'MicroIntImmXOp', 'XURa = XURb - imm;', ['IsMicroop'])
microSubUopCode = '''
URa = URb - shift_rm_imm(URc, shiftAmt, shiftType, OptShiftRmCondCodesC);
'''
microSubUopIop = ArmInstObjParams('sub_uop', 'MicroSubUop',
'MicroIntRegOp',
{ 'code' : microSubUopCode,
'predicate_test' : pickPredicate(microSubUopCode) },
['IsMicroop'])
microUopRegMovIop = ArmInstObjParams('uopReg_uop', 'MicroUopRegMov',
'MicroIntMov',
{ 'code' : 'IWRa = URb;',
'predicate_test' : predicateTest },
['IsMicroop'])
microUopRegMovRetIop = ArmInstObjParams('movret_uop', 'MicroUopRegMovRet',
'MicroIntMov',
{ 'code': microRetUopCode % 'URb',
'predicate_test': predicateTest},
[ 'IsMicroop', 'IsNonSpeculative',
'IsSerializeAfter', 'IsSquashAfter'])
setPCCPSRDecl = '''
CPSR cpsrOrCondCodes = URc;
SCTLR sctlr = Sctlr;
pNPC = URa;
CPSR new_cpsr =
cpsrWriteByInstr(cpsrOrCondCodes, URb, Scr, Nsacr,
0xF, true, sctlr.nmfi, xc->tcBase());
Cpsr = ~CondCodesMask & new_cpsr;
NextThumb = new_cpsr.t;
NextJazelle = new_cpsr.j;
NextItState = ((((CPSR)URb).it2 << 2) & 0xFC)
| (((CPSR)URb).it1 & 0x3);
CondCodesNZ = new_cpsr.nz;
CondCodesC = new_cpsr.c;
CondCodesV = new_cpsr.v;
CondCodesGE = new_cpsr.ge;
'''
microUopSetPCCPSRIop = ArmInstObjParams('uopSet_uop', 'MicroUopSetPCCPSR',
'MicroSetPCCPSR',
{ 'code' : setPCCPSRDecl,
'predicate_test' : predicateTest },
['IsMicroop', 'IsSerializeAfter'])
header_output = MicroIntImmDeclare.subst(microAddiUopIop) + \
MicroIntImmDeclare.subst(microAddXiUopIop) + \
MicroIntImmDeclare.subst(microAddXiSpAlignUopIop) + \
MicroIntImmDeclare.subst(microSubiUopIop) + \
MicroIntImmDeclare.subst(microSubXiUopIop) + \
MicroIntRegDeclare.subst(microAddUopIop) + \
MicroIntRegDeclare.subst(microSubUopIop) + \
MicroIntXERegDeclare.subst(microAddXERegUopIop) + \
MicroIntMovDeclare.subst(microUopRegMovIop) + \
MicroIntMovDeclare.subst(microUopRegMovRetIop) + \
MicroSetPCCPSRDeclare.subst(microUopSetPCCPSRIop)
decoder_output = MicroIntImmConstructor.subst(microAddiUopIop) + \
MicroIntImmXConstructor.subst(microAddXiUopIop) + \
MicroIntImmXConstructor.subst(microAddXiSpAlignUopIop) + \
MicroIntImmConstructor.subst(microSubiUopIop) + \
MicroIntImmXConstructor.subst(microSubXiUopIop) + \
MicroIntRegConstructor.subst(microAddUopIop) + \
MicroIntRegConstructor.subst(microSubUopIop) + \
MicroIntXERegConstructor.subst(microAddXERegUopIop) + \
MicroIntMovConstructor.subst(microUopRegMovIop) + \
MicroIntMovConstructor.subst(microUopRegMovRetIop) + \
MicroSetPCCPSRConstructor.subst(microUopSetPCCPSRIop)
exec_output = PredOpExecute.subst(microAddiUopIop) + \
BasicExecute.subst(microAddXiUopIop) + \
BasicExecute.subst(microAddXiSpAlignUopIop) + \
PredOpExecute.subst(microSubiUopIop) + \
BasicExecute.subst(microSubXiUopIop) + \
PredOpExecute.subst(microAddUopIop) + \
PredOpExecute.subst(microSubUopIop) + \
BasicExecute.subst(microAddXERegUopIop) + \
PredOpExecute.subst(microUopRegMovIop) + \
PredOpExecute.subst(microUopRegMovRetIop) + \
PredOpExecute.subst(microUopSetPCCPSRIop)
}};
let {{
iop = ArmInstObjParams("ldmstm", "LdmStm", 'MacroMemOp', "", [])
header_output = MacroMemDeclare.subst(iop)
decoder_output = MacroMemConstructor.subst(iop)
iop = ArmInstObjParams("ldpstp", "LdpStp", 'PairMemOp', "", [])
header_output += PairMemDeclare.subst(iop)
decoder_output += PairMemConstructor.subst(iop)
iopImm = ArmInstObjParams(
"bigfpmemimm", "BigFpMemImm", "BigFpMemImmOp", "")
iopPre = ArmInstObjParams(
"bigfpmempre", "BigFpMemPre", "BigFpMemPreOp", "")
iopPost = ArmInstObjParams(
"bigfpmempost", "BigFpMemPost", "BigFpMemPostOp", "")
for iop in (iopImm, iopPre, iopPost):
header_output += BigFpMemImmDeclare.subst(iop)
decoder_output += BigFpMemImmConstructor.subst(iop)
iop = ArmInstObjParams("bigfpmemreg", "BigFpMemReg", "BigFpMemRegOp", "")
header_output += BigFpMemRegDeclare.subst(iop)
decoder_output += BigFpMemRegConstructor.subst(iop)
iop = ArmInstObjParams("bigfpmemlit", "BigFpMemLit", "BigFpMemLitOp", "")
header_output += BigFpMemLitDeclare.subst(iop)
decoder_output += BigFpMemLitConstructor.subst(iop)
iop = ArmInstObjParams("vldmult", "VldMult", 'VldMultOp', "", [])
header_output += VMemMultDeclare.subst(iop)
decoder_output += VMemMultConstructor.subst(iop)
iop = ArmInstObjParams("vldsingle", "VldSingle", 'VldSingleOp', "", [])
header_output += VMemSingleDeclare.subst(iop)
decoder_output += VMemSingleConstructor.subst(iop)
iop = ArmInstObjParams("vstmult", "VstMult", 'VstMultOp', "", [])
header_output += VMemMultDeclare.subst(iop)
decoder_output += VMemMultConstructor.subst(iop)
iop = ArmInstObjParams("vstsingle", "VstSingle", 'VstSingleOp', "", [])
header_output += VMemSingleDeclare.subst(iop)
decoder_output += VMemSingleConstructor.subst(iop)
vfpIop = ArmInstObjParams("vldmstm", "VLdmStm", 'MacroVFPMemOp', "", [])
header_output += MacroVFPMemDeclare.subst(vfpIop)
decoder_output += MacroVFPMemConstructor.subst(vfpIop)
}};