GP-4030: Fix MIPS base and eabi 32/64-bit cspecs

GP-4029: Update base PowerPC 32/64-bit cspecs
This commit is contained in:
ghintern 2025-02-25 20:50:19 +00:00 committed by James
parent 12ac4660a1
commit d91aebe74e
26 changed files with 1234 additions and 488 deletions

View file

@ -431,7 +431,23 @@ int4 ParamEntry::getSlot(const Address &addr,int4 skip) const
/// \param sz is the size of the parameter to allocated
/// \param typeAlign is the required byte alignment for the parameter
/// \return the address of the new parameter (or an invalid address)
Address ParamEntry::getAddrBySlot(int4 &slotnum,int4 sz,int4 typeAlign) const
Address ParamEntry::getAddrBySlot(int4 &slotnum, int4 sz, int4 typeAlign) const
{
return getAddrBySlot(slotnum, sz, typeAlign, !isLeftJustified());
}
/// \brief Calculate the storage address assigned when allocating a parameter of a given size
///
/// Assume \b slotnum slots have already been assigned and increment \b slotnum
/// by the number of slots used.
/// Return an invalid address if the size is too small or if there are not enough slots left.
/// \param slotnum is a reference to used slots (which will be updated)
/// \param sz is the size of the parameter to allocated
/// \param typeAlign is the required byte alignment for the parameter
/// \param justifyRight is true if initial bytes are padding for odd data-type sizes
/// \return the address of the new parameter (or an invalid address)
Address ParamEntry::getAddrBySlot(int4 &slotnum,int4 sz,int4 typeAlign, bool justifyRight) const
{
Address res; // Start with an invalid result
@ -471,7 +487,7 @@ Address ParamEntry::getAddrBySlot(int4 &slotnum,int4 sz,int4 typeAlign) const
res = Address(spaceid, addressbase + index * alignment);
slotnum += slotsused; // Inform caller of number of slots used
}
if (!isLeftJustified()) // Adjust for right justified (big endian)
if (justifyRight) // Adjust for right justified (big endian)
res = res + (spaceused - sz);
return res;
}

View file

@ -146,6 +146,7 @@ public:
int4 getSlot(const Address &addr,int4 skip) const;
AddrSpace *getSpace(void) const { return spaceid; } ///< Get the address space containing \b this entry
uintb getBase(void) const { return addressbase; } ///< Get the starting offset of \b this entry
Address getAddrBySlot(int4 &slot, int4 sz, int4 typeAlign, bool justifyRight) const;
Address getAddrBySlot(int4 &slot,int4 sz,int4 typeAlign) const;
void decode(Decoder &decoder,bool normalstack,bool grouped,list<ParamEntry> &curList);
bool isParamCheckHigh(void) const { return ((flags & extracheck_high)!=0); } ///< Return \b true if there is a high overlap

View file

@ -1254,7 +1254,8 @@ AttributeId ATTRIB_WORDSIZE = AttributeId("wordsize",26);
AttributeId ATTRIB_STORAGE = AttributeId("storage",149);
AttributeId ATTRIB_STACKSPILL = AttributeId("stackspill",150);
AttributeId ATTRIB_UNKNOWN = AttributeId("XMLunknown",156); // Number serves as next open index
AttributeId ATTRIB_UNKNOWN = AttributeId("XMLunknown",159); // Number serves as next open index
ElementId ELEM_DATA = ElementId("data",1);
ElementId ELEM_INPUT = ElementId("input",2);

View file

@ -22,6 +22,9 @@ AttributeId ATTRIB_SIZES = AttributeId("sizes",151);
AttributeId ATTRIB_MAX_PRIMITIVES = AttributeId("maxprimitives", 153);
AttributeId ATTRIB_REVERSESIGNIF = AttributeId("reversesignif", 154);
AttributeId ATTRIB_MATCHSIZE = AttributeId("matchsize", 155);
AttributeId ATTRIB_AFTER_BYTES = AttributeId("afterbytes", 156);
AttributeId ATTRIB_AFTER_STORAGE = AttributeId("afterstorage", 157);
AttributeId ATTRIB_FILL_ALTERNATE = AttributeId("fillalternate", 158);
ElementId ELEM_DATATYPE = ElementId("datatype",273);
ElementId ELEM_CONSUME = ElementId("consume",274);
@ -662,7 +665,7 @@ AssignAction *AssignAction::decodeSideeffect(Decoder &decoder,const ParamListSta
action = new ConsumeExtra(res);
}
else if (elemId == ELEM_EXTRA_STACK) {
action = new ExtraStack(res,0);
action = new ExtraStack(res);
}
else if (elemId == ELEM_CONSUME_REMAINING) {
action = new ConsumeRemaining(res);
@ -850,7 +853,7 @@ uint4 MultiSlotAssign::assignAddress(Datatype *dt,const PrototypePieces &proto,i
if (!consumeFromStack)
return fail;
int4 grp = stackEntry->getGroup();
Address addr = stackEntry->getAddrBySlot(tmpStatus[grp],sizeLeft,align); // Consume all the space we need
Address addr = stackEntry->getAddrBySlot(tmpStatus[grp],sizeLeft,align,justifyRight); // Consume all the space we need
if (addr.isInvalid())
return fail;
pieces.push_back(VarnodeData());
@ -1043,11 +1046,15 @@ void MultiSlotDualAssign::initializeEntries(void)
{
resource->extractTiles(baseTiles,baseType);
resource->extractTiles(altTiles,altType);
stackEntry = resource->getStackEntry();
if (baseTiles.size() == 0 || altTiles.size() == 0)
throw LowlevelError("Could not find matching resources for action: join_dual_class");
tileSize = baseTiles[0]->getSize();
if (tileSize != altTiles[0]->getSize())
throw LowlevelError("Storage class register sizes do not match for action: join_dual_class");
if (consumeFromStack && stackEntry == (const ParamEntry *)0)
throw LowlevelError("Cannot find matching stack resource for action: join_dual_class");
}
/// \brief Get the index of the first unused ParamEntry in the given list
@ -1084,6 +1091,8 @@ int4 MultiSlotDualAssign::getTileClass(const PrimitiveExtractor &primitives,int4
int4 res = 1;
int4 count = 0;
int4 endBoundary = off + tileSize;
if (index >= primitives.size()) return -1;
const PrimitiveExtractor::Primitive &firstPrimitive( primitives.get(index) );
while(index < primitives.size()) {
const PrimitiveExtractor::Primitive &element( primitives.get(index) );
if (element.offset < off) return -1;
@ -1096,6 +1105,12 @@ int4 MultiSlotDualAssign::getTileClass(const PrimitiveExtractor &primitives,int4
res = 0;
}
if (count == 0) return -1; // Must be at least one primitive in section
if (fillAlternate) { // Only use altType if the tile contains one primitive of exactly the tile size
if (count > 1)
res = 0;
if (firstPrimitive.dt->getSize() != tileSize)
res = 0;
}
return res;
}
@ -1107,6 +1122,7 @@ MultiSlotDualAssign::MultiSlotDualAssign(const ParamListStandard *res)
fillinOutputActive = true;
baseType = TYPECLASS_GENERAL; // Tile from general purpose registers
altType = TYPECLASS_FLOAT; // Use specialized registers for floating-point components
consumeFromStack = false;
consumeMostSig = false;
justifyRight = false;
AddrSpace *spc = res->getSpacebase();
@ -1114,18 +1130,23 @@ MultiSlotDualAssign::MultiSlotDualAssign(const ParamListStandard *res)
consumeMostSig = true;
justifyRight = true;
}
fillAlternate = false;
tileSize = 0;
stackEntry = (const ParamEntry *)0;
}
MultiSlotDualAssign::MultiSlotDualAssign(type_class baseStore,type_class altStore,bool mostSig,bool justRight,
const ParamListStandard *res)
MultiSlotDualAssign::MultiSlotDualAssign(type_class baseStore,type_class altStore,bool stack,
bool mostSig,bool justRight,bool fillAlt,const ParamListStandard *res)
: AssignAction(res)
{
fillinOutputActive = true;
baseType = baseStore;
altType = altStore;
consumeFromStack = stack;
consumeMostSig = mostSig;
justifyRight = justRight;
fillAlternate = fillAlt;
stackEntry = (const ParamEntry *)0;
initializeEntries();
}
@ -1139,6 +1160,7 @@ uint4 MultiSlotDualAssign::assignAddress(Datatype *dt,const PrototypePieces &pro
vector<int4> tmpStatus = status;
vector<VarnodeData> pieces;
int4 typeSize = dt->getSize();
int4 align = dt->getAlignment();
int4 sizeLeft = typeSize;
int4 iterBase = 0;
int4 iterAlt = 0;
@ -1149,14 +1171,20 @@ uint4 MultiSlotDualAssign::assignAddress(Datatype *dt,const PrototypePieces &pro
return fail;
if (iterType == 0) {
iterBase = getFirstUnused(iterBase, baseTiles, tmpStatus);
if (iterBase == baseTiles.size())
return fail; // Out of general purpose registers
if (iterBase == baseTiles.size()) {
if (!consumeFromStack)
return fail; // Out of general purpose registers
break;
}
entry = baseTiles[iterBase];
}
else {
iterAlt = getFirstUnused(iterAlt, altTiles, tmpStatus);
if (iterAlt == altTiles.size())
return fail; // Out of alternate registers
if (iterAlt == altTiles.size()) {
if (!consumeFromStack)
return fail; // Out of alternate registers
break;
}
entry = altTiles[iterAlt];
}
int4 trialSize = entry->getSize();
@ -1168,6 +1196,18 @@ uint4 MultiSlotDualAssign::assignAddress(Datatype *dt,const PrototypePieces &pro
pieces.back().size = trialSize;
sizeLeft -= trialSize;
}
if (sizeLeft > 0) {
if (!consumeFromStack)
return fail;
int4 grp = stackEntry->getGroup();
Address addr = stackEntry->getAddrBySlot(tmpStatus[grp],sizeLeft,align,justifyRight); // Consume all the space we need
if (addr.isInvalid())
return fail;
pieces.push_back(VarnodeData());
pieces.back().space = addr.getSpace();
pieces.back().offset = addr.getOffset();
pieces.back().size = sizeLeft;
}
if (sizeLeft < 0) { // Have odd data-type size
if (justifyRight) {
pieces.front().offset += -sizeLeft; // Initial bytes of first entry are padding
@ -1248,7 +1288,7 @@ void MultiSlotDualAssign::decode(Decoder &decoder)
uint4 attribId = decoder.getNextAttributeId();
if (attribId == 0) break;
if (attribId == ATTRIB_REVERSEJUSTIFY) {
if (decoder.readBool())
if (decoder.readBool())
justifyRight = !justifyRight;
}
else if (attribId == ATTRIB_REVERSESIGNIF) {
@ -1261,6 +1301,12 @@ void MultiSlotDualAssign::decode(Decoder &decoder)
else if (attribId == ATTRIB_B) {
altType = string2typeclass(decoder.readString());
}
else if (attribId == ATTRIB_STACKSPILL) {
consumeFromStack = decoder.readBool();
}
else if (attribId == ATTRIB_FILL_ALTERNATE) {
fillAlternate = decoder.readBool();
}
}
decoder.closeElement(elemId);
initializeEntries(); // Need new firstIter
@ -1459,16 +1505,19 @@ void ExtraStack::initializeEntry(void)
}
/// \param res is the new resource set to associate with \b this action
/// \param val is a dummy value
ExtraStack::ExtraStack(const ParamListStandard *res,int4 val)
: AssignAction(res)
{
stackEntry = (const ParamEntry *)0;
}
ExtraStack::ExtraStack(const ParamListStandard *res)
: AssignAction(res)
{
afterBytes = -1;
afterStorage = TYPECLASS_GENERAL;
stackEntry = (const ParamEntry *)0;
}
ExtraStack::ExtraStack(type_class storage, int4 offset, const ParamListStandard *res)
: AssignAction(res)
{
afterStorage = storage;
afterBytes = offset;
stackEntry = (const ParamEntry *)0;
initializeEntry();
}
@ -1479,6 +1528,26 @@ uint4 ExtraStack::assignAddress(Datatype *dt,const PrototypePieces &proto,int4 p
if (res.addr.getSpace() == stackEntry->getSpace())
return success; // Parameter was already assigned to the stack
int4 grp = stackEntry->getGroup();
// Check whether we have consumed enough storage to need to adjust the stack yet
if (afterBytes > 0) {
const list<ParamEntry>& entryList = resource->getEntry();
int4 bytesConsumed = 0;
list<ParamEntry>::const_iterator iter = entryList.begin();
list<ParamEntry>::const_iterator endIter = entryList.end();
while (iter != endIter) {
const ParamEntry &entry(*iter);
++iter;
if (entry.getGroup() == grp || entry.getType() != afterStorage) {
continue;
}
if (status[entry.getGroup()] != 0) {
bytesConsumed += entry.getSize();
}
}
if (bytesConsumed < afterBytes) {
return success;
}
}
// We assign the stack address (but ignore the actual address) updating the status for the stack,
// which consumes the stack resources.
stackEntry->getAddrBySlot(status[grp],dt->getSize(),dt->getAlignment());
@ -1489,6 +1558,14 @@ void ExtraStack::decode(Decoder &decoder)
{
uint4 elemId = decoder.openElement(ELEM_EXTRA_STACK);
for (;;) {
uint4 attribId = decoder.getNextAttributeId();
if (attribId == 0) break;
else if (attribId == ATTRIB_AFTER_BYTES)
afterBytes = decoder.readUnsignedInteger();
else if (attribId == ATTRIB_AFTER_STORAGE)
afterStorage = string2typeclass(decoder.readString());
}
decoder.closeElement(elemId);
initializeEntry();
}

View file

@ -32,6 +32,9 @@ extern AttributeId ATTRIB_SIZES; ///< Marshaling attribute "sizes"
extern AttributeId ATTRIB_MAX_PRIMITIVES; ///< Marshaling attribute "maxprimitives"
extern AttributeId ATTRIB_REVERSESIGNIF; ///< Marshaling attribute "reversesignif"
extern AttributeId ATTRIB_MATCHSIZE; ///< Marshaling attribute "matchsize"
extern AttributeId ATTRIB_AFTER_BYTES; ///< Marshaling attribute "afterbytes"
extern AttributeId ATTRIB_AFTER_STORAGE; ///< Marshaling attribute "afterstorage"
extern AttributeId ATTRIB_FILL_ALTERNATE; ///< Marshalling attribute "fillalternate"
extern ElementId ELEM_DATATYPE; ///< Marshaling element \<datatype>
extern ElementId ELEM_CONSUME; ///< Marshaling element \<consume>
@ -396,20 +399,24 @@ public:
class MultiSlotDualAssign : public AssignAction {
type_class baseType; ///< Resource list from which to consume general tiles
type_class altType; ///< Resource list from which to consume alternate tiles
bool consumeFromStack; ///< True if resources should be consumed from the stack
bool consumeMostSig; ///< True if resources are consumed starting with most significant bytes
bool justifyRight; ///< True if initial bytes are padding for odd data-type sizes
bool fillAlternate; ///< True if a single primitive needs to fill an alternate tile
int4 tileSize; ///< Number of bytes in a tile
vector<const ParamEntry *> baseTiles; ///< General registers to be joined
vector<const ParamEntry *> altTiles; ///< Alternate registers to be joined
const ParamEntry *stackEntry; ///< The stack resource
void initializeEntries(void); ///< Cache specific ParamEntry needed by the action
int4 getFirstUnused(int4 iter,const vector<const ParamEntry *> &tiles,vector<int4> &status) const;
int4 getTileClass(const PrimitiveExtractor &primitives,int4 off,int4 &index) const;
public:
MultiSlotDualAssign(const ParamListStandard *res); ///< Constructor for use with decode
MultiSlotDualAssign(type_class baseStore,type_class altStore,bool mostSig,bool justRight,
const ParamListStandard *res); ///< Constructor
MultiSlotDualAssign(type_class baseStore,type_class altStore,bool stack,bool mostSig,
bool justRight,bool fillAlt,const ParamListStandard *res); ///< Constructor
virtual AssignAction *clone(const ParamListStandard *newResource) const {
return new MultiSlotDualAssign(baseType,altType,consumeMostSig,justifyRight,newResource); }
return new MultiSlotDualAssign(baseType,altType,consumeFromStack,consumeMostSig,justifyRight,
fillAlternate,newResource); }
virtual uint4 assignAddress(Datatype *dt,const PrototypePieces &proto,int4 pos,TypeFactory &tlist,
vector<int4> &status,ParameterPieces &res) const;
virtual bool fillinOutputMap(ParamActive *active) const;
@ -484,13 +491,15 @@ public:
/// stack resources as if the parameter were allocated to the stack. If the current parameter was
/// already assigned a stack address, no additional action is taken.
class ExtraStack : public AssignAction {
int4 afterBytes; ///< Activate side effect after given number of bytes consumed
type_class afterStorage; ///< Activate side effect after given amount of this storage consumed
const ParamEntry *stackEntry; ///< Parameter Entry corresponding to the stack
void initializeEntry(void); ///< Find stack entry in resource list
public:
ExtraStack(const ParamListStandard *res,int4 val); ///< Constructor for use with decode
ExtraStack(const ParamListStandard *res); ///< Constructor
ExtraStack(const ParamListStandard *res); ///< Constructor for use with decode
ExtraStack(type_class storage,int4 offset,const ParamListStandard *res); ///< Constructor
virtual AssignAction *clone(const ParamListStandard *newResource) const {
return new ExtraStack(newResource); }
return new ExtraStack(afterStorage,afterBytes,newResource); }
virtual uint4 assignAddress(Datatype *dt,const PrototypePieces &proto,int4 pos,TypeFactory &tlist,
vector<int4> &status,ParameterPieces &res) const;
virtual void decode(Decoder &decoder);

View file

@ -449,6 +449,16 @@
<attribute name="reversesignif">
<ref name="boolean_type"/>
</attribute>
</optional>
<optional>
<attribute name="stackspill">
<ref name="boolean_type"/>
</attribute>
</optional>
<optional>
<attribute name="fillalternate">
<ref name="boolean_type"/>
</attribute>
</optional>
<optional>
<attribute name="storage"/>
@ -461,6 +471,16 @@
</optional>
</element>
</choice>
<zeroOrMore>
<element name="extra_stack">
<optional>
<attribute name="afterbytes"/>
</optional>
<optional>
<attribute name="afterstorage"/>
</optional>
</element>
</zeroOrMore>
<zeroOrMore>
<element name="consume_extra">
<attribute name="storage"/>
@ -474,13 +494,8 @@
<zeroOrMore>
<element name="consume_remaining">
<attribute name="storage"/>
</element>
</zeroOrMore>
<zeroOrMore>
<element name="extra_stack">
<empty/>
</element>
</zeroOrMore>
</element>
</zeroOrMore>
</define>
<define name="prototype_type">

View file

@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -338,6 +338,22 @@ public class ParamEntry {
* @return slotnum plus the number of slots used
*/
public int getAddrBySlot(int slotnum, int sz, int typeAlign, ParameterPieces res) {
return getAddrBySlot(slotnum, sz, typeAlign, res, !isLeftJustified());
}
/**
* Assign the storage address when allocating something of size -sz- assuming -slotnum- slots
* have already been assigned. Set the address to null if the -sz- is too small or if
* there are not enough slots left
* @param slotnum number of slots already assigned
* @param sz number of bytes to being assigned
* @param typeAlign required byte alignment for the parameter
* @param res will hold the final storage address
* @param justifyRight true if initial bytes are padding for odd data-type sizes
* @return slotnum plus the number of slots used
*/
public int getAddrBySlot(int slotnum, int sz, int typeAlign, ParameterPieces res,
boolean justifyRight) {
int spaceused;
long offset;
res.address = null; // Start with an invalid result
@ -387,7 +403,7 @@ public class ParamEntry {
offset = addressbase + index * alignment;
slotnum += slotsused; // Inform caller of number of slots used
}
if (!isLeftJustified()) {
if (justifyRight) {
offset += (spaceused - sz);
}
res.address = spaceid.getAddress(offset);

View file

@ -15,15 +15,19 @@
*/
package ghidra.program.model.lang.protorules;
import static ghidra.program.model.pcode.AttributeId.*;
import static ghidra.program.model.pcode.ElementId.*;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map.Entry;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.DataTypeManager;
import ghidra.program.model.lang.*;
import ghidra.program.model.pcode.Encoder;
import ghidra.util.exception.InvalidInputException;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.*;
/**
@ -37,6 +41,8 @@ import ghidra.xml.*;
public class ExtraStack extends AssignAction {
private ParamEntry stackEntry; // Parameter entry corresponding to the stack
private int afterBytes; // Activate side effect after given number of bytes consumed
private StorageClass afterStorage; // Active side effect after given amount of this storage consumed
/**
* Find stack entry in resource list
@ -64,17 +70,22 @@ public class ExtraStack extends AssignAction {
public ExtraStack(ParamListStandard res, int val) {
super(res);
stackEntry = null;
afterStorage = StorageClass.GENERAL;
afterBytes = -1;
}
public ExtraStack(ParamListStandard res) throws InvalidInputException {
public ExtraStack(StorageClass storage, int offset, ParamListStandard res)
throws InvalidInputException {
super(res);
stackEntry = null;
afterStorage = storage;
afterBytes = offset;
initializeEntry();
}
@Override
public AssignAction clone(ParamListStandard newResource) throws InvalidInputException {
return new ExtraStack(newResource);
return new ExtraStack(afterStorage, afterBytes, newResource);
}
@Override
@ -82,7 +93,13 @@ public class ExtraStack extends AssignAction {
if (this.getClass() != op.getClass()) {
return false;
}
ExtraStack otherAction = (ExtraStack) op;
if (afterBytes != otherAction.afterBytes || afterStorage != otherAction.afterStorage) {
return false;
}
return stackEntry.isEquivalent(otherAction.stackEntry);
}
@ -93,6 +110,21 @@ public class ExtraStack extends AssignAction {
return SUCCESS; // Parameter was already assigned to the stack
}
int grp = stackEntry.getGroup();
// Check whether we have consumed enough storage to need to adjust stack yet
if (afterBytes > 0) {
int bytesConsumed = 0;
for (int i = 0; i < resource.getNumParamEntry(); i++) {
if (i == grp || resource.getEntry(i).getType() != afterStorage) {
continue;
}
if (status[i] != 0) {
bytesConsumed += resource.getEntry(i).getSize();
}
}
if (bytesConsumed < afterBytes) {
return SUCCESS; // Don't yet need to consume extra stack space
}
}
// We assign the stack address (but ignore the actual address) updating the status for the stack,
// which consumes the stack resources.
ParameterPieces unused = new ParameterPieces();
@ -104,12 +136,34 @@ public class ExtraStack extends AssignAction {
@Override
public void encode(Encoder encoder) throws IOException {
encoder.openElement(ELEM_EXTRA_STACK);
if (afterBytes >= 0) {
encoder.writeUnsignedInteger(ATTRIB_AFTER_BYTES, afterBytes);
}
if (afterStorage != StorageClass.GENERAL) {
encoder.writeString(ATTRIB_STORAGE, afterStorage.toString());
}
encoder.closeElement(ELEM_EXTRA_STACK);
}
private void restoreAttributesXml(XmlElement el) throws XmlParseException {
Iterator<Entry<String, String>> iter = el.getAttributes().entrySet().iterator();
while (iter.hasNext()) {
Entry<String, String> attrib = iter.next();
String nm = attrib.getKey();
if (nm.equals(ATTRIB_AFTER_BYTES.name())) {
afterBytes = SpecXmlUtils.decodeInt(attrib.getValue());
}
else if (nm.equals(ATTRIB_AFTER_STORAGE.name())) {
afterStorage = StorageClass.getClass(attrib.getValue());
}
}
}
@Override
public void restoreXml(XmlPullParser parser) throws XmlParseException {
XmlElement elem = parser.start(ELEM_EXTRA_STACK.name());
restoreAttributesXml(elem);
parser.end(elem);
try {
initializeEntry();

View file

@ -227,7 +227,8 @@ public class MultiSlotAssign extends AssignAction {
return FAIL;
}
int grp = stackEntry.getGroup();
tmpStatus[grp] = stackEntry.getAddrBySlot(tmpStatus[grp], sizeLeft, align, param); // Consume all the space we need
tmpStatus[grp] =
stackEntry.getAddrBySlot(tmpStatus[grp], sizeLeft, align, param, justifyRight); // Consume all the space we need
if (param.address == null) {
return FAIL;
}

View file

@ -42,11 +42,14 @@ import ghidra.xml.*;
public class MultiSlotDualAssign extends AssignAction {
private StorageClass baseType; // Resource list from which to consume general tiles
private StorageClass altType; // Resource list from which to consume alternate tiles
private boolean consumeFromStack; // True if resources can be consumed from the stack
private boolean consumeMostSig; // True if resources are consumed starting with most significant bytes
private boolean justifyRight; // True if initial bytes are padding for odd data-type sizes
private boolean fillAlternate; // True if a single primitive needs to fill an alternate tile
private int tileSize; // Number of bytes in a tile
private ParamEntry[] baseTiles; // General registers for joining
private ParamEntry[] altTiles; // Alternate registers for joininig
private ParamEntry[] altTiles; // Alternate registers for joining
private ParamEntry stackEntry; // The stack resource
/**
* Find the first ParamEntry matching the baseType, and the first matching altType.
@ -55,6 +58,7 @@ public class MultiSlotDualAssign extends AssignAction {
private void initializeEntries() throws InvalidInputException {
baseTiles = resource.extractTiles(baseType);
altTiles = resource.extractTiles(altType);
stackEntry = resource.extractStack();
if (baseTiles.length == 0 || altTiles.length == 0) {
throw new InvalidInputException(
"Could not find matching resources for action: join_dual_class");
@ -64,6 +68,10 @@ public class MultiSlotDualAssign extends AssignAction {
throw new InvalidInputException(
"Storage class register sizes do not match for action: join_dual_class");
}
if (consumeFromStack && stackEntry == null) {
throw new InvalidInputException(
"Cannot find matching stack resource for action: join_dual_class");
}
}
/**
@ -101,6 +109,10 @@ public class MultiSlotDualAssign extends AssignAction {
int res = 1;
int count = 0;
int endBoundary = off + tileSize;
if (index[0] >= primitives.size()) {
return -1;
}
Primitive firstPrimitive = primitives.get(index[0]);
while (index[0] < primitives.size()) {
Primitive element = primitives.get(index[0]);
if (element.offset < off) {
@ -122,6 +134,14 @@ public class MultiSlotDualAssign extends AssignAction {
if (count == 0) {
return -1; // Must be at least one primitive in section
}
if (fillAlternate) { // Only use altType if the tile contains one primitive of exactly the tile size
if (count > 1) {
res = 0;
}
if (firstPrimitive.dt.getLength() != tileSize) {
res = 0;
}
}
return res;
}
@ -133,29 +153,47 @@ public class MultiSlotDualAssign extends AssignAction {
super(res);
baseType = StorageClass.GENERAL; // Tile from general purpose registers
altType = StorageClass.FLOAT; // Use specialized registers for floating-point components
consumeFromStack = false;
consumeMostSig = false;
justifyRight = false;
if (res.getEntry(0).isBigEndian()) {
consumeMostSig = true;
justifyRight = true;
}
fillAlternate = false;
tileSize = 0;
stackEntry = null;
}
public MultiSlotDualAssign(StorageClass baseStore, StorageClass altStore, boolean mostSig,
boolean justRight, ParamListStandard res) throws InvalidInputException {
/**
* Constructor
* @param baseStore resource list from which to consume general tiles
* @param altStore resource list form which to consume alternate tiles
* @param stack true if resources can be consumed from the stack
* @param mostSig true if resources are consumed starting with most significant bytes
* @param justRight true if initial bytes are padding for odd data-type sizes
* @param fillAlt true if a single primitive needs to fill an alternate tile
* @param res is the new resource set to associate with this action
* @throws InvalidInputException if the required elements are not available in the resource list
*/
public MultiSlotDualAssign(StorageClass baseStore, StorageClass altStore, boolean stack,
boolean mostSig, boolean justRight, boolean fillAlt, ParamListStandard res)
throws InvalidInputException {
super(res);
baseType = baseStore;
altType = altStore;
consumeFromStack = stack;
consumeMostSig = mostSig;
justifyRight = justRight;
fillAlternate = fillAlt;
stackEntry = null;
initializeEntries();
}
@Override
public AssignAction clone(ParamListStandard newResource) throws InvalidInputException {
return new MultiSlotDualAssign(baseType, altType, consumeMostSig, justifyRight,
newResource);
return new MultiSlotDualAssign(baseType, altType, consumeFromStack, consumeMostSig,
justifyRight, fillAlternate, newResource);
}
@Override
@ -164,8 +202,10 @@ public class MultiSlotDualAssign extends AssignAction {
return false;
}
MultiSlotDualAssign otherAction = (MultiSlotDualAssign) op;
if (consumeMostSig != otherAction.consumeMostSig ||
justifyRight != otherAction.justifyRight) {
if (consumeFromStack != otherAction.consumeFromStack ||
consumeMostSig != otherAction.consumeMostSig ||
justifyRight != otherAction.justifyRight ||
fillAlternate != otherAction.fillAlternate) {
return false;
}
if (baseType != otherAction.baseType || altType != otherAction.altType) {
@ -203,6 +243,7 @@ public class MultiSlotDualAssign extends AssignAction {
int[] tmpStatus = status.clone();
ArrayList<Varnode> pieces = new ArrayList<>();
int typeSize = dt.getLength();
int align = dt.getAlignment();
int sizeLeft = typeSize;
int iterBase = 0;
int iterAlt = 0;
@ -215,14 +256,20 @@ public class MultiSlotDualAssign extends AssignAction {
if (iterType == 0) {
iterBase = getFirstUnused(iterBase, baseTiles, tmpStatus);
if (iterBase == baseTiles.length) {
return FAIL; // Out of general registers
if (!consumeFromStack) {
return FAIL; // Out of general registers
}
break;
}
entry = baseTiles[iterBase];
}
else {
iterAlt = getFirstUnused(iterAlt, altTiles, tmpStatus);
if (iterAlt == altTiles.length) {
return FAIL; // Out of alternate registers
if (!consumeFromStack) {
return FAIL; // Out of alternate registers
}
break;
}
entry = altTiles[iterAlt];
}
@ -233,6 +280,19 @@ public class MultiSlotDualAssign extends AssignAction {
pieces.add(vn);
sizeLeft -= trialSize;
}
if (sizeLeft > 0) { // Have to use stack to get enough bytes
if (!consumeFromStack) {
return FAIL;
}
int grp = stackEntry.getGroup();
tmpStatus[grp] =
stackEntry.getAddrBySlot(tmpStatus[grp], sizeLeft, align, param, justifyRight);
if (param.address == null) {
return FAIL;
}
Varnode vn = new Varnode(param.address, sizeLeft);
pieces.add(vn);
}
if (sizeLeft < 0) { // Have odd data-type size
if (justifyRight) {
// Initial bytes of first entry are padding
@ -271,6 +331,8 @@ public class MultiSlotDualAssign extends AssignAction {
if (altType != StorageClass.FLOAT) {
encoder.writeString(ATTRIB_B, altType.toString());
}
encoder.writeBool(ATTRIB_STACKSPILL, consumeFromStack);
encoder.writeBool(ATTRIB_FILL_ALTERNATE, fillAlternate);
encoder.closeElement(ELEM_JOIN);
}
@ -295,6 +357,12 @@ public class MultiSlotDualAssign extends AssignAction {
else if (name.equals(ATTRIB_B.name())) {
altType = StorageClass.getClass(attrib.getValue());
}
else if (name.equals(ATTRIB_STACKSPILL.name())) {
consumeFromStack = SpecXmlUtils.decodeBoolean(attrib.getValue());
}
else if (name.equals(ATTRIB_FILL_ALTERNATE.name())) {
fillAlternate = SpecXmlUtils.decodeBoolean(attrib.getValue());
}
}
parser.end(elem);
try {

View file

@ -247,10 +247,13 @@ public record AttributeId(String name, int id) {
// modelrules
public static final AttributeId ATTRIB_SIZES = new AttributeId("sizes", 151);
public static final AttributeId ATTRIB_BACKFILL = new AttributeId("backfill", 152);
public static final AttributeId ATTRIB_MAX_PRIMITIVES = new AttributeId("maxprimitives", 153);
public static final AttributeId ATTRIB_REVERSESIGNIF = new AttributeId("reversesignif", 154);
public static final AttributeId ATTRIB_MATCHSIZE = new AttributeId("matchsize", 155);
public static final AttributeId ATTRIB_AFTER_BYTES = new AttributeId("afterbytes", 156);
public static final AttributeId ATTRIB_AFTER_STORAGE = new AttributeId("afterstorage", 157);
public static final AttributeId ATTRIB_FILL_ALTERNATE = new AttributeId("fillalternate", 158);
public static final AttributeId ATTRIB_UNKNOWN = new AttributeId("XMLunknown", 159);
public static final AttributeId ATTRIB_UNKNOWN = new AttributeId("XMLunknown", 156);
}

View file

@ -11,22 +11,22 @@ data/languages/mips32Instructions.sinc||GHIDRA||||END|
data/languages/mips32R6.pspec||GHIDRA||||END|
data/languages/mips32R6be.slaspec||GHIDRA||||END|
data/languages/mips32R6le.slaspec||GHIDRA||||END|
data/languages/mips32_eabi.cspec||GHIDRA||||END|
data/languages/mips32_fp64.cspec||GHIDRA||||END|
data/languages/mips32be.cspec||GHIDRA||||END|
data/languages/mips32be.slaspec||GHIDRA||||END|
data/languages/mips32be_eabi.cspec||GHIDRA||||END|
data/languages/mips32le.cspec||GHIDRA||||END|
data/languages/mips32le.slaspec||GHIDRA||||END|
data/languages/mips32le_eabi.cspec||GHIDRA||||END|
data/languages/mips32micro.pspec||GHIDRA||||END|
data/languages/mips64.cspec||GHIDRA||||END|
data/languages/mips64.pspec||GHIDRA||||END|
data/languages/mips64Instructions.sinc||GHIDRA||||END|
data/languages/mips64R6.pspec||GHIDRA||||END|
data/languages/mips64_32_n32.cspec||GHIDRA||||END|
data/languages/mips64_32_o32.cspec||GHIDRA||||END|
data/languages/mips64_32_o64.cspec||GHIDRA||||END|
data/languages/mips64be.cspec||GHIDRA||||END|
data/languages/mips64be.slaspec||GHIDRA||||END|
data/languages/mips64le.cspec||GHIDRA||||END|
data/languages/mips64le.slaspec||GHIDRA||||END|
data/languages/mips64micro.pspec||GHIDRA||||END|
data/languages/mips_dsp.sinc||GHIDRA||||END|

View file

@ -12,7 +12,7 @@
<description>MIPS32 32-bit addresses, big endian, with mips16e</description>
<compiler name="default" spec="mips32be.cspec" id="default"/>
<compiler name="Visual Studio" spec="mips32be.cspec" id="windows"/>
<compiler name="eabi" spec="mips32be_eabi.cspec" id="eabi"/>
<compiler name="eabi" spec="mips32_eabi.cspec" id="eabi"/>
<external_name tool="gnu" name="mips:3000"/>
<external_name tool="gnu" name="mips:4000"/>
<external_name tool="IDA-PRO" name="mipsb"/>
@ -32,7 +32,7 @@
<description>MIPS32 32-bit addresses, little endian, with mips16e</description>
<compiler name="default" spec="mips32le.cspec" id="default"/>
<compiler name="Visual Studio" spec="mips32le.cspec" id="windows"/>
<compiler name="eabi" spec="mips32le_eabi.cspec" id="eabi"/>
<compiler name="eabi" spec="mips32_eabi.cspec" id="eabi"/>
<external_name tool="gnu" name="mips:3000"/>
<external_name tool="gnu" name="mips:4000"/>
<external_name tool="IDA-PRO" name="mipsl"/>
@ -82,7 +82,7 @@
manualindexfile="../manuals/mipsM16.idx"
id="MIPS:BE:64:default">
<description>MIPS64 64-bit addresses, big endian, with mips16e</description>
<compiler name="default" spec="mips64.cspec" id="default"/>
<compiler name="default" spec="mips64be.cspec" id="default"/>
<external_name tool="gnu" name="mips:5000"/>
<external_name tool="IDA-PRO" name="mipsb"/>
<external_name tool="IDA-PRO" name="r5900r"/>
@ -100,8 +100,8 @@
manualindexfile="../manuals/mipsM16.idx"
id="MIPS:LE:64:default">
<description>MIPS64 64-bit addreses, little endian, with mips16e</description>
<compiler name="default" spec="mips64.cspec" id="default"/>
<compiler name="Visual Studio" spec="mips64.cspec" id="windows"/>
<compiler name="default" spec="mips64le.cspec" id="default"/>
<compiler name="Visual Studio" spec="mips64le.cspec" id="windows"/>
<external_name tool="gnu" name="mips:5000"/>
<external_name tool="IDA-PRO" name="mipsl"/>
<external_name tool="IDA-PRO" name="r5900l"/>
@ -119,7 +119,7 @@
manualindexfile="../manuals/mipsMic.idx"
id="MIPS:BE:64:micro">
<description>MIPS64 64-bit addresses, big endian, with microMIPS</description>
<compiler name="default" spec="mips64.cspec" id="default"/>
<compiler name="default" spec="mips64be.cspec" id="default"/>
<external_name tool="IDA-PRO" name="mipsb"/>
<external_name tool="IDA-PRO" name="r5900r"/>
<external_name tool="DWARF.register.mapping.file" name="mips.dwarf"/>
@ -134,8 +134,8 @@
manualindexfile="../manuals/mipsMic.idx"
id="MIPS:LE:64:micro">
<description>MIPS64 64-bit addresses, little endian, with microMIPS</description>
<compiler name="default" spec="mips64.cspec" id="default"/>
<compiler name="Visual Studio" spec="mips64.cspec" id="windows"/>
<compiler name="default" spec="mips64le.cspec" id="default"/>
<compiler name="Visual Studio" spec="mips64le.cspec" id="windows"/>
<external_name tool="IDA-PRO" name="mipsl"/>
<external_name tool="IDA-PRO" name="r5900l"/>
<external_name tool="DWARF.register.mapping.file" name="mips.dwarf"/>
@ -150,7 +150,7 @@
manualindexfile="../manuals/mipsMic.idx"
id="MIPS:BE:64:R6">
<description>MIPS64 Release-6 64-bit addresses, big endian, with microMIPS</description>
<compiler name="default" spec="mips64.cspec" id="default"/>
<compiler name="default" spec="mips64be.cspec" id="default"/>
<external_name tool="IDA-PRO" name="mipsb"/>
<external_name tool="IDA-PRO" name="r5900r"/>
<external_name tool="DWARF.register.mapping.file" name="mips.dwarf"/>
@ -167,8 +167,8 @@
manualindexfile="../manuals/mipsMic.idx"
id="MIPS:LE:64:R6">
<description>MIPS64 Release-6 64-bit addresses, little endian, with microMIPS</description>
<compiler name="default" spec="mips64.cspec" id="default"/>
<compiler name="Visual Studio" spec="mips64.cspec" id="windows"/>
<compiler name="default" spec="mips64le.cspec" id="default"/>
<compiler name="Visual Studio" spec="mips64le.cspec" id="windows"/>
<external_name tool="IDA-PRO" name="mipsl"/>
<external_name tool="IDA-PRO" name="r5900l"/>
<external_name tool="DWARF.register.mapping.file" name="mips.dwarf"/>

View file

@ -2,7 +2,12 @@
<compiler_spec>
<data_organization>
<char_size value="1"/>
<short_size value="2"/>
<integer_size value="4"/>
<pointer_size value="4"/>
<long_size value="4"/>
<long_long_size value="8"/>
<float_size value="4" />
<double_size value="8" />
<long_double_size value="8" />
@ -65,6 +70,34 @@
<pentry minsize="1" maxsize="500" align="4">
<addr offset="0" space="stack"/>
</pentry>
<rule>
<datatype name="homogeneous-float-aggregate" maxprimitives="1"/>
<join_per_primitive storage="float"/>
</rule>
<rule>
<datatype name="homogeneous-float-aggregate" maxprimitives="1"/>
<goto_stack/>
</rule>
<rule>
<datatype name="float"/>
<consume storage="float"/>
</rule>
<rule>
<datatype name="float"/>
<goto_stack/>
</rule>
<rule>
<datatype name="struct" minsize="5"/>
<convert_to_ptr/>
</rule>
<rule>
<datatype name="union" minsize="5"/>
<convert_to_ptr/>
</rule>
<rule>
<datatype name="any"/>
<join align="true"/>
</rule>
</input>
<output>
<pentry minsize="1" maxsize="8" metatype="float">
@ -73,9 +106,21 @@
<pentry minsize="1" maxsize="4">
<register name="v0"/>
</pentry>
<pentry minsize="5" maxsize="8">
<addr space="join" piece1="v0" piece2="v1"/>
<pentry minsize="1" maxsize="4">
<register name="v1"/>
</pentry>
<rule>
<datatype name="homogeneous-float-aggregate" maxprimitives="1"/>
<join_per_primitive storage="float"/>
</rule>
<rule>
<datatype name="float"/>
<consume storage="float"/>
</rule>
<rule>
<datatype name="any"/>
<join/>
</rule>
</output>
<unaffected>
<register name="s0"/>
@ -97,21 +142,11 @@
<register name="f30"/>
</unaffected>
<killedbycall>
<register name="at"/>
<register name="a0"/>
<register name="a1"/>
<register name="a2"/>
<register name="a3"/>
<register name="t0"/>
<register name="t1"/>
<register name="t2"/>
<register name="t3"/>
<register name="t4"/>
<register name="t5"/>
<register name="t6"/>
<register name="t7"/>
<register name="t8"/>
<register name="t9"/>
<register name="at"/>
<register name="v0"/>
<register name="v1"/>
<register name="f0"/>
<register name="f1"/>
</killedbycall>
<localrange>
<range space="stack" first="0xfff0bdc0" last="0xffffffff"/>

View file

@ -25,6 +25,7 @@
</returnaddress>
<default_proto>
<prototype name="__stdcall" extrapop="0" stackshift="0">
<!-- This is based on the System V ABI -->
<input>
<pentry minsize="1" maxsize="8" metatype="float">
<register name="f12_13"/>
@ -47,6 +48,52 @@
<pentry minsize="1" maxsize="500" align="4">
<addr offset="16" space="stack"/>
</pentry>
<!-- Parameters within the ellipses only use integer registers -->
<rule>
<datatype name="float"/>
<varargs first="0"/>
<consume storage="general"/>
</rule>
<!-- special case: first two args are float,double, which produces a 'hole' in the
second word of the argument space, which must be explicitly consumed -->
<rule>
<datatype name="float" minsize="1" maxsize="4"/>
<position index="0"/>
<datatype_at index="1">
<datatype name="float" minsize="5" maxsize="8"/>
</datatype_at>
<consume storage="float"/>
<consume_extra storage="general"/>
<consume_extra storage="general"/>
</rule>
<!-- Only leading floating-point parameters can use float registers -->
<rule>
<datatype name="float" minsize="1" maxsize="8"/> <!-- float parameter -->
<position index="0"/> <!-- as first input parameter -->
<consume storage="float"/> <!-- use f12_f13 -->
<consume_extra storage="general"/>
</rule>
<rule>
<datatype name="float" minsize="1" maxsize="8"/> <!-- float parameter -->
<position index="1"/> <!-- as second input parameter -->
<datatype_at index="0"> <!-- if the first input -->
<datatype name="float" minsize="1" maxsize="8"/> <!-- is a float parameter -->
</datatype_at>
<consume storage="float"/> <!-- use f14_f15 -->
<consume_extra storage="general"/>
</rule>
<rule>
<datatype name="struct"/>
<join align="true" reversejustify="true"/>
</rule>
<rule>
<datatype name="union"/>
<join align="true" reversejustify="true"/>
</rule>
<rule>
<datatype name="any"/> <!-- otherwise any parameter -->
<join align="true"/> <!-- should split across general purpose registers -->
</rule>
</input>
<output>
<pentry minsize="1" maxsize="8" metatype="float">
@ -55,9 +102,25 @@
<pentry minsize="1" maxsize="4">
<register name="v0"/>
</pentry>
<pentry minsize="5" maxsize="8">
<addr space="join" piece1="v0" piece2="v1"/>
<pentry minsize="1" maxsize="4">
<register name="v1"/>
</pentry>
<rule>
<datatype name="float"/>
<consume storage="float"/>
</rule>
<rule>
<datatype name="struct"/>
<hidden_return/> <!-- structures always passed as hidden return parameter -->
</rule>
<rule>
<datatype name="union"/>
<hidden_return/> <!-- unions always passed as hidden return parameter -->
</rule>
<rule>
<datatype name="any"/>
<join/>
</rule>
</output>
<unaffected>
<register name="s0"/>
@ -72,12 +135,24 @@
<register name="sp"/>
<register name="gp"/>
<register name="f20"/>
<register name="f21"/>
<register name="f22"/>
<register name="f23"/>
<register name="f24"/>
<register name="f25"/>
<register name="f26"/>
<register name="f27"/>
<register name="f28"/>
<register name="f29"/>
<register name="f30"/>
</unaffected>
<killedbycall>
<register name="at"/>
<register name="v0"/>
<register name="v1"/>
<register name="f0"/>
<register name="f1"/>
</killedbycall>
<internal_storage>
<register name="gp"/> <!-- Compilers may save gp to the stack before a call and restore it afterward -->
</internal_storage>

View file

@ -47,6 +47,44 @@
<pentry minsize="1" maxsize="500" align="4">
<addr offset="16" space="stack"/>
</pentry>
<!-- Parameters within the ellipses only use integer registers -->
<rule>
<datatype name="float"/>
<varargs first="0"/>
<consume storage="general"/>
</rule>
<!-- special case: first two args are float,double, which produces a 'hole' in the
second word of the argument space, which must be explicitly consumed -->
<rule>
<datatype name="float" minsize="1" maxsize="4"/>
<position index="0"/>
<datatype_at index="1">
<datatype name="float" minsize="5" maxsize="8"/>
</datatype_at>
<consume storage="float"/>
<consume_extra storage="general"/>
<consume_extra storage="general"/>
</rule>
<!-- Only leading floating-point parameters can use float registers -->
<rule>
<datatype name="float" minsize="1" maxsize="8"/> <!-- float parameter -->
<position index="0"/> <!-- as first input parameter -->
<consume storage="float"/> <!-- use f12_f13 -->
<consume_extra storage="general"/>
</rule>
<rule>
<datatype name="float" minsize="1" maxsize="8"/> <!-- float parameter -->
<position index="1"/> <!-- as second input parameter -->
<datatype_at index="0"> <!-- if the first input -->
<datatype name="float" minsize="1" maxsize="8"/> <!-- is a float parameter -->
</datatype_at>
<consume storage="float"/> <!-- use f14_f15 -->
<consume_extra storage="general"/>
</rule>
<rule>
<datatype name="any"/> <!-- otherwise any parameter -->
<join align="true"/> <!-- should split across general purpose registers -->
</rule>
</input>
<output>
<pentry minsize="1" maxsize="8" metatype="float">
@ -55,9 +93,25 @@
<pentry minsize="1" maxsize="4">
<register name="v0"/>
</pentry>
<pentry minsize="5" maxsize="8">
<addr space="join" piece1="v1" piece2="v0"/>
<pentry minsize="1" maxsize="4">
<register name="v1"/>
</pentry>
<rule>
<datatype name="float"/>
<consume storage="float"/>
</rule>
<rule>
<datatype name="struct"/>
<hidden_return/> <!-- structures always passed as hidden return parameter -->
</rule>
<rule>
<datatype name="union"/>
<hidden_return/> <!-- unions always passed as hidden return parameter -->
</rule>
<rule>
<datatype name="any"/>
<join/>
</rule>
</output>
<unaffected>
<register name="s0"/>
@ -72,12 +126,24 @@
<register name="sp"/>
<register name="gp"/>
<register name="f20"/>
<register name="f21"/>
<register name="f22"/>
<register name="f23"/>
<register name="f24"/>
<register name="f25"/>
<register name="f26"/>
<register name="f27"/>
<register name="f28"/>
<register name="f29"/>
<register name="f30"/>
</unaffected>
<killedbycall>
<register name="at"/>
<register name="v0"/>
<register name="v1"/>
<register name="f0"/>
<register name="f1"/>
</killedbycall>
<internal_storage>
<register name="gp"/> <!-- Compilers may save gp to the stack before a call and restore it afterward -->
</internal_storage>

View file

@ -1,123 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<compiler_spec>
<data_organization>
<pointer_size value="4"/>
<float_size value="4" />
<double_size value="8" />
<long_double_size value="8" />
<size_alignment_map>
<entry size="1" alignment="1" />
<entry size="2" alignment="2" />
<entry size="4" alignment="4" />
<entry size="8" alignment="8" />
</size_alignment_map>
</data_organization>
<stackpointer register="sp" space="ram"/>
<funcptr align="2"/>
<global>
<range space="ram"/>
<range space="register" first="0x2000" last="0x2fff"/>
</global>
<returnaddress>
<register name="ra"/>
</returnaddress>
<default_proto>
<prototype name="__stdcall" extrapop="0" stackshift="0">
<input>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="f12_13"/>
</pentry>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="f14_15"/>
</pentry>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="f16_17"/>
</pentry>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="f18_19"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="a0"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="a1"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="a2"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="a3"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="t0"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="t1"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="t2"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="t3"/>
</pentry>
<pentry minsize="1" maxsize="500" align="4">
<addr offset="0" space="stack"/>
</pentry>
</input>
<output>
<pentry minsize="1" maxsize="8" metatype="float">
<register name="f0_1"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="v0"/>
</pentry>
<pentry minsize="5" maxsize="8">
<addr space="join" piece1="v1" piece2="v0"/>
</pentry>
</output>
<unaffected>
<register name="s0"/>
<register name="s1"/>
<register name="s2"/>
<register name="s3"/>
<register name="s4"/>
<register name="s5"/>
<register name="s6"/>
<register name="s7"/>
<register name="s8"/>
<register name="sp"/>
<register name="gp"/>
<register name="f20"/>
<register name="f22"/>
<register name="f24"/>
<register name="f26"/>
<register name="f28"/>
<register name="f30"/>
</unaffected>
<killedbycall>
<register name="at"/>
<register name="a0"/>
<register name="a1"/>
<register name="a2"/>
<register name="a3"/>
<register name="t0"/>
<register name="t1"/>
<register name="t2"/>
<register name="t3"/>
<register name="t4"/>
<register name="t5"/>
<register name="t6"/>
<register name="t7"/>
<register name="t8"/>
<register name="t9"/>
</killedbycall>
<localrange>
<range space="stack" first="0xfff0bdc0" last="0xffffffff"/>
<range space="stack" first="0" last="15"/> <!-- This is backup storage space for register params, but we treat as locals -->
</localrange>
</prototype>
</default_proto>
</compiler_spec>

View file

@ -1,111 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<compiler_spec>
<data_organization>
<pointer_size value="8"/>
<float_size value="4" />
<double_size value="8" />
<long_double_size value="16" />
<size_alignment_map>
<entry size="1" alignment="1" />
<entry size="2" alignment="2" />
<entry size="4" alignment="4" />
<entry size="8" alignment="8" />
</size_alignment_map>
</data_organization>
<stackpointer register="sp" space="ram"/>
<funcptr align="2"/>
<global>
<range space="ram"/>
<range space="register" first="0x2000" last="0x2fff"/>
</global>
<aggressivetrim signext="true"/> <!-- Aggressively try to eliminate sign extensions -->
<default_proto>
<prototype name="__stdcall" extrapop="0" stackshift="0">
<input killedbycall="true">
<pentry minsize="1" maxsize="8" metatype="float">
<register name="f12"/>
</pentry>
<pentry minsize="1" maxsize="8" metatype="float">
<register name="f13"/>
</pentry>
<pentry minsize="1" maxsize="8" metatype="float">
<register name="f14"/>
</pentry>
<pentry minsize="1" maxsize="8" metatype="float">
<register name="f15"/>
</pentry>
<pentry minsize="1" maxsize="8" metatype="float">
<register name="f16"/>
</pentry>
<pentry minsize="1" maxsize="8" metatype="float">
<register name="f17"/>
</pentry>
<pentry minsize="1" maxsize="8" metatype="float">
<register name="f18"/>
</pentry>
<pentry minsize="1" maxsize="8" metatype="float">
<register name="f19"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="a0"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="a1"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="a2"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="a3"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="t0"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="t1"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="t2"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="t3"/>
</pentry>
<pentry minsize="1" maxsize="500" align="8">
<addr offset="0" space="stack"/>
</pentry>
</input>
<output>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="f0"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="v0"/>
</pentry>
<pentry minsize="9" maxsize="16">
<addr space="join" piece1="v0" piece2="v1"/>
</pentry>
</output>
<unaffected>
<register name="s0"/>
<register name="s1"/>
<register name="s2"/>
<register name="s3"/>
<register name="s4"/>
<register name="s5"/>
<register name="s6"/>
<register name="s7"/>
<register name="s8"/>
<register name="sp"/>
<register name="gp"/>
<register name="f24"/>
<register name="f25"/>
<register name="f26"/>
<register name="f27"/>
<register name="f28"/>
<register name="f29"/>
<register name="f30"/>
<register name="f31"/>
</unaffected>
</prototype>
</default_proto>
</compiler_spec>

View file

@ -0,0 +1,189 @@
<?xml version="1.0" encoding="UTF-8"?>
<compiler_spec>
<data_organization>
<pointer_size value="8"/>
<integer_size value="4" />
<long_size value="8" />
<float_size value="4" />
<double_size value="8" />
<long_double_size value="16" />
<size_alignment_map>
<entry size="1" alignment="1" />
<entry size="2" alignment="2" />
<entry size="4" alignment="4" />
<entry size="8" alignment="8" />
</size_alignment_map>
</data_organization>
<stackpointer register="sp" space="ram"/>
<funcptr align="2"/>
<global>
<range space="ram"/>
<range space="register" first="0x2000" last="0x2fff"/>
</global>
<aggressivetrim signext="true"/> <!-- Aggressively try to eliminate sign extensions -->
<default_proto>
<prototype name="__stdcall" extrapop="0" stackshift="0">
<input>
<group>
<pentry minsize="1" maxsize="8" metatype="float">
<register name="f12"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="a0"/>
</pentry>
</group>
<group>
<pentry minsize="1" maxsize="8" metatype="float">
<register name="f13"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="a1"/>
</pentry>
</group>
<group>
<pentry minsize="1" maxsize="8" metatype="float">
<register name="f14"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="a2"/>
</pentry>
</group>
<group>
<pentry minsize="1" maxsize="8" metatype="float">
<register name="f15"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="a3"/>
</pentry>
</group>
<group>
<pentry minsize="1" maxsize="8" metatype="float">
<register name="f16"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="t0"/>
</pentry>
</group>
<group>
<pentry minsize="1" maxsize="8" metatype="float">
<register name="f17"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="t1"/>
</pentry>
</group>
<group>
<pentry minsize="1" maxsize="8" metatype="float">
<register name="f18"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="t2"/>
</pentry>
</group>
<group>
<pentry minsize="1" maxsize="8" metatype="float">
<register name="f19"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="t3"/>
</pentry>
</group>
<pentry minsize="1" maxsize="500" align="8">
<addr offset="0" space="stack"/>
</pentry>
<rule>
<datatype name="float"/>
<varargs first="0"/>
<join reversejustify="true"/>
</rule>
<rule>
<datatype name="struct"/>
<varargs first="0"/>
<join reversejustify="true"/>
</rule>
<rule>
<datatype name="float"/>
<consume storage="float"/>
</rule>
<rule>
<datatype name="float"/>
<join reversejustify="true"/>
</rule>
<rule>
<datatype name="struct"/>
<join_dual_class stackspill="true" fillalternate="true" reversejustify="true"/>
</rule>
<rule>
<datatype name="union"/>
<join reversejustify="true"/>
</rule>
<rule>
<datatype name="any"/>
<join/>
</rule>
</input>
<output>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="f0"/>
</pentry>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="f2"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="v0"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="v1"/>
</pentry>
<rule>
<datatype name="homogeneous-float-aggregate"/>
<join_per_primitive storage="float"/>
</rule>
<rule>
<datatype name="float"/>
<consume storage="float"/>
</rule>
<rule>
<datatype name="struct"/>
<join reversejustify="true"/>
</rule>
<rule>
<datatype name="union"/>
<join reversejustify="true"/>
</rule>
<rule>
<datatype name="any"/>
<join/>
</rule>
</output>
<unaffected>
<register name="s0"/>
<register name="s1"/>
<register name="s2"/>
<register name="s3"/>
<register name="s4"/>
<register name="s5"/>
<register name="s6"/>
<register name="s7"/>
<register name="s8"/>
<register name="sp"/>
<register name="gp"/>
<register name="f24"/>
<register name="f25"/>
<register name="f26"/>
<register name="f27"/>
<register name="f28"/>
<register name="f29"/>
<register name="f30"/>
<register name="f31"/>
</unaffected>
<killedbycall>
<register name="at"/>
<register name="v0"/>
<register name="v1"/>
<register name="f0"/>
<register name="f2"/>
</killedbycall>
</prototype>
</default_proto>
</compiler_spec>

View file

@ -0,0 +1,173 @@
<?xml version="1.0" encoding="UTF-8"?>
<compiler_spec>
<data_organization>
<pointer_size value="8"/>
<integer_size value="4" />
<long_size value="8" />
<float_size value="4" />
<double_size value="8" />
<long_double_size value="16" />
<size_alignment_map>
<entry size="1" alignment="1" />
<entry size="2" alignment="2" />
<entry size="4" alignment="4" />
<entry size="8" alignment="8" />
</size_alignment_map>
</data_organization>
<stackpointer register="sp" space="ram"/>
<funcptr align="2"/>
<global>
<range space="ram"/>
<range space="register" first="0x2000" last="0x2fff"/>
</global>
<aggressivetrim signext="true"/> <!-- Aggressively try to eliminate sign extensions -->
<default_proto>
<prototype name="__stdcall" extrapop="0" stackshift="0">
<input>
<group>
<pentry minsize="1" maxsize="8" metatype="float">
<register name="f12"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="a0"/>
</pentry>
</group>
<group>
<pentry minsize="1" maxsize="8" metatype="float">
<register name="f13"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="a1"/>
</pentry>
</group>
<group>
<pentry minsize="1" maxsize="8" metatype="float">
<register name="f14"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="a2"/>
</pentry>
</group>
<group>
<pentry minsize="1" maxsize="8" metatype="float">
<register name="f15"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="a3"/>
</pentry>
</group>
<group>
<pentry minsize="1" maxsize="8" metatype="float">
<register name="f16"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="t0"/>
</pentry>
</group>
<group>
<pentry minsize="1" maxsize="8" metatype="float">
<register name="f17"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="t1"/>
</pentry>
</group>
<group>
<pentry minsize="1" maxsize="8" metatype="float">
<register name="f18"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="t2"/>
</pentry>
</group>
<group>
<pentry minsize="1" maxsize="8" metatype="float">
<register name="f19"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="t3"/>
</pentry>
</group>
<pentry minsize="1" maxsize="500" align="8">
<addr offset="0" space="stack"/>
</pentry>
<rule>
<datatype name="float"/>
<varargs first="0"/>
<consume storage="general"/>
</rule>
<rule>
<datatype name="struct"/>
<varargs first="0"/>
<join/>
</rule>
<rule>
<datatype name="float"/>
<consume storage="float"/>
</rule>
<rule>
<datatype name="struct"/>
<join_dual_class stackspill="true" fillalternate="true"/>
</rule>
<rule>
<datatype name="any"/>
<join/>
</rule>
</input>
<output>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="f0"/>
</pentry>
<pentry minsize="4" maxsize="8" metatype="float">
<register name="f2"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="v0"/>
</pentry>
<pentry minsize="1" maxsize="8">
<register name="v1"/>
</pentry>
<rule>
<datatype name="homogeneous-float-aggregate"/>
<join_per_primitive storage="float"/>
</rule>
<rule>
<datatype name="float"/>
<consume storage="float"/>
</rule>
<rule>
<datatype name="any"/>
<join/>
</rule>
</output>
<unaffected>
<register name="s0"/>
<register name="s1"/>
<register name="s2"/>
<register name="s3"/>
<register name="s4"/>
<register name="s5"/>
<register name="s6"/>
<register name="s7"/>
<register name="s8"/>
<register name="sp"/>
<register name="gp"/>
<register name="f24"/>
<register name="f25"/>
<register name="f26"/>
<register name="f27"/>
<register name="f28"/>
<register name="f29"/>
<register name="f30"/>
<register name="f31"/>
</unaffected>
<killedbycall>
<register name="at"/>
<register name="v0"/>
<register name="v1"/>
<register name="f0"/>
<register name="f2"/>
</killedbycall>
</prototype>
</default_proto>
</compiler_spec>

View file

@ -20,10 +20,10 @@ data/languages/old/oldPPC.lang||GHIDRA||||END|
data/languages/old/oldPPC.trans||GHIDRA||||END|
data/languages/ppc.dwarf||GHIDRA||||END|
data/languages/ppc.ldefs||GHIDRA||||END|
data/languages/ppc_32.cspec||GHIDRA||||END|
data/languages/ppc_32.pspec||GHIDRA||||END|
data/languages/ppc_32_4xx_be.slaspec||GHIDRA||||END|
data/languages/ppc_32_4xx_le.slaspec||GHIDRA||||END|
data/languages/ppc_32_be.cspec||GHIDRA||||END|
data/languages/ppc_32_be.slaspec||GHIDRA||||END|
data/languages/ppc_32_be_Mac.cspec||GHIDRA||||END|
data/languages/ppc_32_e500_be.cspec||GHIDRA||||END|
@ -34,14 +34,13 @@ data/languages/ppc_32_e500mc_be.cspec||GHIDRA||||END|
data/languages/ppc_32_e500mc_be.slaspec||GHIDRA||||END|
data/languages/ppc_32_e500mc_le.cspec||GHIDRA||||END|
data/languages/ppc_32_e500mc_le.slaspec||GHIDRA||||END|
data/languages/ppc_32_le.cspec||GHIDRA||||END|
data/languages/ppc_32_le.slaspec||GHIDRA||||END|
data/languages/ppc_32_mpc8270.pspec||GHIDRA||||END|
data/languages/ppc_32_quicciii_be.slaspec||GHIDRA||||END|
data/languages/ppc_32_quicciii_le.slaspec||GHIDRA||||END|
data/languages/ppc_64.cspec||GHIDRA||||END|
data/languages/ppc_64.pspec||GHIDRA||||END|
data/languages/ppc_64_32.cspec||GHIDRA||||END|
data/languages/ppc_64_be.cspec||GHIDRA||||END|
data/languages/ppc_64_be.slaspec||GHIDRA||||END|
data/languages/ppc_64_be_Mac.cspec||GHIDRA||||END|
data/languages/ppc_64_isa_altivec_be.slaspec||GHIDRA||||END|
@ -50,6 +49,7 @@ data/languages/ppc_64_isa_altivec_vle_be.slaspec||GHIDRA||||END|
data/languages/ppc_64_isa_be.slaspec||GHIDRA||||END|
data/languages/ppc_64_isa_le.slaspec||GHIDRA||||END|
data/languages/ppc_64_isa_vle_be.slaspec||GHIDRA||||END|
data/languages/ppc_64_le.cspec||GHIDRA||||END|
data/languages/ppc_64_le.slaspec||GHIDRA||||END|
data/languages/ppc_a2.sinc||GHIDRA||||END|
data/languages/ppc_common.sinc||GHIDRA||||END|

View file

@ -11,7 +11,7 @@
manualindexfile="../manuals/PowerPC.idx"
id="PowerPC:BE:32:default">
<description>PowerPC 32-bit big endian w/Altivec, G2</description>
<compiler name="default" spec="ppc_32_be.cspec" id="default"/>
<compiler name="default" spec="ppc_32.cspec" id="default"/>
<compiler name="Mac OS X" spec="ppc_32_be_Mac.cspec" id="macosx"/>
<external_name tool="gnu" name="powerpc:common"/>
<external_name tool="IDA-PRO" name="ppc"/>
@ -29,8 +29,8 @@
manualindexfile="../manuals/PowerPC.idx"
id="PowerPC:LE:32:default">
<description>PowerPC 32-bit little endian w/Altivec, G2</description>
<compiler name="default" spec="ppc_32_le.cspec" id="default"/>
<compiler name="Visual Studio" spec="ppc_32_le.cspec" id="windows"/>
<compiler name="default" spec="ppc_32.cspec" id="default"/>
<compiler name="Visual Studio" spec="ppc_32.cspec" id="windows"/>
<external_name tool="gnu" name="powerpc:common"/>
<external_name tool="IDA-PRO" name="ppcl"/>
<external_name tool="DWARF.register.mapping.file" name="ppc.dwarf"/>
@ -45,7 +45,7 @@
manualindexfile="../manuals/PowerPC.idx"
id="PowerPC:BE:64:default">
<description>PowerPC 64-bit big endian w/Altivec, G2</description>
<compiler name="default" spec="ppc_64.cspec" id="default"/>
<compiler name="default" spec="ppc_64_be.cspec" id="default"/>
<compiler name="Mac OS X" spec="ppc_64_be_Mac.cspec" id="macosx"/>
<external_name tool="gnu" name="powerpc:common64"/>
<external_name tool="IDA-PRO" name="ppc"/>
@ -98,7 +98,7 @@
manualindexfile="../manuals/PowerPC.idx"
id="PowerPC:LE:64:default">
<description>PowerPC 64-bit little endian w/Altivec, G2</description>
<compiler name="default" spec="ppc_64.cspec" id="default"/>
<compiler name="default" spec="ppc_64_le.cspec" id="default"/>
<external_name tool="gnu" name="powerpc:common64"/>
<external_name tool="IDA-PRO" name="ppcl"/>
<external_name tool="DWARF.register.mapping.file" name="ppc.dwarf"/>
@ -115,7 +115,7 @@
manualindexfile="../manuals/PowerPC.idx"
id="PowerPC:BE:32:4xx">
<description>PowerPC 4xx 32-bit big endian embedded core</description>
<compiler name="default" spec="ppc_32_be.cspec" id="default"/>
<compiler name="default" spec="ppc_32.cspec" id="default"/>
<external_name tool="gnu" name="powerpc:403"/>
<external_name tool="IDA-PRO" name="ppc"/>
<external_name tool="DWARF.register.mapping.file" name="ppc.dwarf"/>
@ -132,8 +132,8 @@
manualindexfile="../manuals/PowerPC.idx"
id="PowerPC:LE:32:4xx">
<description>PowerPC 4xx 32-bit little endian embedded core</description>
<compiler name="default" spec="ppc_32_le.cspec" id="default"/>
<compiler name="Visual Studio" spec="ppc_32_le.cspec" id="windows"/>
<compiler name="default" spec="ppc_32.cspec" id="default"/>
<compiler name="Visual Studio" spec="ppc_32.cspec" id="windows"/>
<external_name tool="gnu" name="powerpc:403"/>
<external_name tool="IDA-PRO" name="ppcl"/>
<external_name tool="DWARF.register.mapping.file" name="ppc.dwarf"/>
@ -148,7 +148,7 @@
manualindexfile="../manuals/PowerPC.idx"
id="PowerPC:BE:32:MPC8270">
<description>Freescale MPC8280 32-bit big endian family (PowerQUICC-III)</description>
<compiler name="default" spec="ppc_32_be.cspec" id="default"/>
<compiler name="default" spec="ppc_32.cspec" id="default"/>
<external_name tool="gnu" name="powerpc:MPC8XX"/>
<external_name tool="IDA-PRO" name="ppc"/>
<external_name tool="DWARF.register.mapping.file" name="ppc.dwarf"/>
@ -165,7 +165,7 @@
manualindexfile="../manuals/PowerPC.idx"
id="PowerPC:BE:32:QUICC">
<description>PowerQUICC-III 32-bit big endian family</description>
<compiler name="default" spec="ppc_32_be.cspec" id="default"/>
<compiler name="default" spec="ppc_32.cspec" id="default"/>
<external_name tool="gnu" name="powerpc:MPC8XX"/>
<external_name tool="IDA-PRO" name="ppc"/>
<external_name tool="DWARF.register.mapping.file" name="ppc.dwarf"/>
@ -182,8 +182,8 @@
manualindexfile="../manuals/PowerPC.idx"
id="PowerPC:LE:32:QUICC">
<description>PowerQUICC-III 32-bit little endian family</description>
<compiler name="default" spec="ppc_32_le.cspec" id="default"/>
<compiler name="Visual Studio" spec="ppc_32_le.cspec" id="windows"/>
<compiler name="default" spec="ppc_32.cspec" id="default"/>
<compiler name="Visual Studio" spec="ppc_32.cspec" id="windows"/>
<external_name tool="gnu" name="powerpc:MPC8XX"/>
<external_name tool="IDA-PRO" name="ppcl"/>
<external_name tool="DWARF.register.mapping.file" name="ppc.dwarf"/>
@ -334,7 +334,7 @@
manualindexfile="../manuals/PowerISA.idx"
id="PowerPC:BE:64:A2ALT">
<description>Power ISA 3.0 Big Endian w/Altivec</description>
<compiler name="default" spec="ppc_64.cspec" id="default"/>
<compiler name="default" spec="ppc_64_be.cspec" id="default"/>
<external_name tool="gnu" name="powerpc:e500mc"/>
<external_name tool="IDA-PRO" name="ppc"/>
<external_name tool="DWARF.register.mapping.file" name="ppc.dwarf"/>
@ -351,7 +351,7 @@
manualindexfile="../manuals/PowerISA.idx"
id="PowerPC:LE:64:A2ALT">
<description>Power ISA 3.0 Little Endian w/Altivec</description>
<compiler name="default" spec="ppc_64.cspec" id="default"/>
<compiler name="default" spec="ppc_64_le.cspec" id="default"/>
<external_name tool="gnu" name="powerpc:e500mc"/>
<external_name tool="IDA-PRO" name="ppcl"/>
<external_name tool="DWARF.register.mapping.file" name="ppc.dwarf"/>

View file

@ -32,21 +32,6 @@
<pentry minsize="1" maxsize="8" metatype="float" extension="float">
<register name="f8"/>
</pentry>
<pentry minsize="1" maxsize="8" metatype="float" extension="float">
<register name="f9"/>
</pentry>
<pentry minsize="1" maxsize="8" metatype="float" extension="float">
<register name="f10"/>
</pentry>
<pentry minsize="1" maxsize="8" metatype="float" extension="float">
<register name="f11"/>
</pentry>
<pentry minsize="1" maxsize="8" metatype="float" extension="float">
<register name="f12"/>
</pentry>
<pentry minsize="1" maxsize="8" metatype="float" extension="float">
<register name="f13"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="r3"/>
</pentry>
@ -74,6 +59,26 @@
<pentry minsize="1" maxsize="500" align="4">
<addr offset="8" space="stack"/>
</pentry>
<rule>
<datatype name="float"/>
<consume storage="float"/>
</rule>
<rule>
<datatype name="float"/>
<goto_stack/>
</rule>
<rule>
<datatype name="struct"/>
<convert_to_ptr/>
</rule>
<rule>
<datatype name="union"/>
<convert_to_ptr/>
</rule>
<rule>
<datatype name="any"/>
<join align="true"/>
</rule>
</input>
<output>
<pentry minsize="1" maxsize="8" metatype="float" extension="float">
@ -82,9 +87,17 @@
<pentry minsize="1" maxsize="4" extension="inttype">
<register name="r3"/>
</pentry>
<pentry minsize="5" maxsize="8">
<addr space="join" piece1="r4" piece2="r3"/>
<pentry minsize="1" maxsize="4" extension="inttype">
<register name="r4"/>
</pentry>
<rule>
<datatype name="float"/>
<consume storage="float"/>
</rule>
<rule>
<datatype name="any"/>
<join/>
</rule>
</output>
<unaffected>
<register name="r1"/> <!-- stack pointer -->
@ -108,10 +121,33 @@
<register name="r29"/>
<register name="r30"/>
<register name="r31"/>
<register name="f14"/>
<register name="f15"/>
<register name="f16"/>
<register name="f17"/>
<register name="f18"/>
<register name="f19"/>
<register name="f20"/>
<register name="f21"/>
<register name="f22"/>
<register name="f23"/>
<register name="f24"/>
<register name="f25"/>
<register name="f26"/>
<register name="f27"/>
<register name="f28"/>
<register name="f29"/>
<register name="f30"/>
<register name="f31"/>
<register name="cr2"/>
<register name="cr3"/>
<register name="cr4"/>
</unaffected>
<killedbycall>
<register name="r3"/>
<register name="r4"/>
<register name="f1"/>
</killedbycall>
</prototype>
</default_proto>

View file

@ -1,127 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<compiler_spec>
<global>
<range space="ram"/>
</global>
<stackpointer register="r1" space="ram"/>
<default_proto>
<prototype name="__stdcall" extrapop="0" stackshift="0">
<input pointermax="8">
<pentry minsize="1" maxsize="8" metatype="float" extension="float">
<register name="f1"/>
</pentry>
<pentry minsize="1" maxsize="8" metatype="float" extension="float">
<register name="f2"/>
</pentry>
<pentry minsize="1" maxsize="8" metatype="float" extension="float">
<register name="f3"/>
</pentry>
<pentry minsize="1" maxsize="8" metatype="float" extension="float">
<register name="f4"/>
</pentry>
<pentry minsize="1" maxsize="8" metatype="float" extension="float">
<register name="f5"/>
</pentry>
<pentry minsize="1" maxsize="8" metatype="float" extension="float">
<register name="f6"/>
</pentry>
<pentry minsize="1" maxsize="8" metatype="float" extension="float">
<register name="f7"/>
</pentry>
<pentry minsize="1" maxsize="8" metatype="float" extension="float">
<register name="f8"/>
</pentry>
<pentry minsize="1" maxsize="8" metatype="float" extension="float">
<register name="f9"/>
</pentry>
<pentry minsize="1" maxsize="8" metatype="float" extension="float">
<register name="f10"/>
</pentry>
<pentry minsize="1" maxsize="8" metatype="float" extension="float">
<register name="f11"/>
</pentry>
<pentry minsize="1" maxsize="8" metatype="float" extension="float">
<register name="f12"/>
</pentry>
<pentry minsize="1" maxsize="8" metatype="float" extension="float">
<register name="f13"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="r3"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="r4"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="r5"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="r6"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="r7"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="r8"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="r9"/>
</pentry>
<pentry minsize="1" maxsize="4">
<register name="r10"/>
</pentry>
<pentry minsize="1" maxsize="500" align="4">
<addr offset="8" space="stack"/>
</pentry>
</input>
<output>
<pentry minsize="1" maxsize="8" metatype="float" extension="float">
<register name="f1"/>
</pentry>
<pentry minsize="1" maxsize="4" extension="inttype">
<register name="r3"/>
</pentry>
<pentry minsize="5" maxsize="8">
<addr space="join" piece1="r3" piece2="r4"/>
</pentry>
</output>
<unaffected>
<register name="r1"/> <!-- stack pointer -->
<register name="r2"/> <!-- _SDA2_BASE_ -->
<register name="r13"/> <!-- _SDA_BASE_ -->
<register name="r14"/>
<register name="r15"/>
<register name="r16"/>
<register name="r17"/>
<register name="r18"/>
<register name="r19"/>
<register name="r20"/>
<register name="r21"/>
<register name="r22"/>
<register name="r23"/>
<register name="r24"/>
<register name="r25"/>
<register name="r26"/>
<register name="r27"/>
<register name="r28"/>
<register name="r29"/>
<register name="r30"/>
<register name="r31"/>
<register name="cr2"/>
<register name="cr3"/>
<register name="cr4"/>
</unaffected>
</prototype>
</default_proto>
<callfixup name="get_pc_thunk_lr">
<target name="__get_pc_thunk_lr"/>
<pcode>
<body><![CDATA[
LR = inst_dest + 4;
]]></body>
</pcode>
</callfixup>
</compiler_spec>

View file

@ -0,0 +1,203 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- This cspec is based upon the PowerPC 64-bit ELF ABI specification -->
<!-- Very similar to the PowerPC 64-bit little-endian cspec, but reverses justification when
assigning odd datatype sizes -->
<compiler_spec>
<data_organization>
<machine_alignment value="8" />
<default_alignment value="1" />
<default_pointer_alignment value="8" />
<pointer_size value="8" />
<wchar_size value="4" />
<short_size value="2" />
<integer_size value="4" />
<long_size value="8" />
<long_long_size value="8" />
<float_size value="4" />
<double_size value="8" />
<long_double_size value="16" />
<size_alignment_map>
<entry size="1" alignment="1" />
<entry size="2" alignment="2" />
<entry size="4" alignment="4" />
<entry size="8" alignment="8" />
<entry size="16" alignment="16" />
</size_alignment_map>
</data_organization>
<global>
<range space="ram"/>
</global>
<stackpointer register="r1" space="ram"/>
<default_proto>
<prototype name="__stdcall" extrapop="0" stackshift="0">
<input>
<pentry minsize="1" maxsize="8" metatype="float" extension="float">
<register name="f1"/>
</pentry>
<pentry minsize="1" maxsize="8" metatype="float" extension="float">
<register name="f2"/>
</pentry>
<pentry minsize="1" maxsize="8" metatype="float" extension="float">
<register name="f3"/>
</pentry>
<pentry minsize="1" maxsize="8" metatype="float" extension="float">
<register name="f4"/>
</pentry>
<pentry minsize="1" maxsize="8" metatype="float" extension="float">
<register name="f5"/>
</pentry>
<pentry minsize="1" maxsize="8" metatype="float" extension="float">
<register name="f6"/>
</pentry>
<pentry minsize="1" maxsize="8" metatype="float" extension="float">
<register name="f7"/>
</pentry>
<pentry minsize="1" maxsize="8" metatype="float" extension="float">
<register name="f8"/>
</pentry>
<pentry minsize="1" maxsize="8" metatype="float" extension="float">
<register name="f9"/>
</pentry>
<pentry minsize="1" maxsize="8" metatype="float" extension="float">
<register name="f10"/>
</pentry>
<pentry minsize="1" maxsize="8" metatype="float" extension="float">
<register name="f11"/>
</pentry>
<pentry minsize="1" maxsize="8" metatype="float" extension="float">
<register name="f12"/>
</pentry>
<pentry minsize="1" maxsize="8" metatype="float" extension="float">
<register name="f13"/>
</pentry>
<pentry minsize="1" maxsize="8" extension="inttype">
<register name="r3"/>
</pentry>
<pentry minsize="1" maxsize="8" extension="inttype">
<register name="r4"/>
</pentry>
<pentry minsize="1" maxsize="8" extension="inttype">
<register name="r5"/>
</pentry>
<pentry minsize="1" maxsize="8" extension="inttype">
<register name="r6"/>
</pentry>
<pentry minsize="1" maxsize="8" extension="inttype">
<register name="r7"/>
</pentry>
<pentry minsize="1" maxsize="8" extension="inttype">
<register name="r8"/>
</pentry>
<pentry minsize="1" maxsize="8" extension="inttype">
<register name="r9"/>
</pentry>
<pentry minsize="1" maxsize="8" extension="inttype">
<register name="r10"/>
</pentry>
<pentry minsize="1" maxsize="500" align="8">
<addr offset="112" space="stack"/>
</pentry>
<rule>
<datatype name="homogeneous-float-aggregate" maxprimitives="1"/>
<join storage="float"/>
<extra_stack afterstorage="general" afterbytes="64"/>
<consume_extra storage="general"/>
</rule>
<rule>
<datatype name="float"/>
<join storage="float"/> <!-- The join is NOT aligned -->
<extra_stack afterstorage="general" afterbytes="64"/>
<consume_extra storage="general"/>
</rule>
<!-- Values are packed big-endian within registers, but packing registers and stack dwords
together is done in the little-endian fashion -->
<rule>
<datatype name="struct" minsize="8"/>
<join align="true" reversejustify="true"/>
</rule>
<rule>
<datatype name="union" minsize="8"/>
<join align="true" reversejustify="true"/>
</rule>
<rule>
<datatype name="any"/>
<join align="true"/> <!-- The join IS aligned -->
</rule>
</input>
<output>
<pentry minsize="1" maxsize="8" metatype="float" extension="float">
<register name="f1"/>
</pentry>
<pentry minsize="1" maxsize="8" extension="inttype">
<register name="r3"/>
</pentry>
<rule>
<datatype name="struct"/>
<convert_to_ptr/>
</rule>
<rule>
<datatype name="union"/>
<convert_to_ptr/>
</rule>
</output>
<unaffected>
<register name="r14"/>
<register name="r15"/>
<register name="r16"/>
<register name="r17"/>
<register name="r18"/>
<register name="r19"/>
<register name="r20"/>
<register name="r21"/>
<register name="r22"/>
<register name="r23"/>
<register name="r24"/>
<register name="r25"/>
<register name="r26"/>
<register name="r27"/>
<register name="r28"/>
<register name="r29"/>
<register name="r30"/>
<register name="r31"/>
<register name="r1"/>
<!-- In cases where r2 does change, we assume it will get restored -->
<register name="r2"/>
<register name="r2Save"/>
<register name="f14"/>
<register name="f15"/>
<register name="f16"/>
<register name="f17"/>
<register name="f18"/>
<register name="f19"/>
<register name="f20"/>
<register name="f21"/>
<register name="f22"/>
<register name="f23"/>
<register name="f24"/>
<register name="f25"/>
<register name="f26"/>
<register name="f27"/>
<register name="f28"/>
<register name="f29"/>
<register name="f30"/>
<register name="f31"/>
<register name="cr2"/>
<register name="cr3"/>
<register name="cr4"/>
</unaffected>
<killedbycall>
<register name="r3"/>
<register name="f1"/>
</killedbycall>
<pcode inject="uponreturn">
<body>
# Inject pcode when returning from a function call to place the r2Save
# value into 0x28(r1) which should be restored by the "ld r2,0x28(r1)"
# which immediately follows calls which comply with the PPC64 ABI spec.
local saveR2ptr = r1 + 0x28;
*:8 saveR2ptr = r2Save;
</body>
</pcode>
</prototype>
</default_proto>
</compiler_spec>

View file

@ -1,8 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- This cspec is based upon the PowerPC 64-bit ELF ABI specification -->
<!-- Very similar to the PowerPC 64-bit big-endian cspec, but does not reverse justification when
assigning odd datatype sizes -->
<compiler_spec>
<data_organization>
<pointer_size value="8"/>
<machine_alignment value="8" />
<default_alignment value="1" />
<default_pointer_alignment value="8" />
<pointer_size value="8" />
<wchar_size value="4" />
<short_size value="2" />
<integer_size value="4" />
<long_size value="8" />
<long_long_size value="8" />
<float_size value="4" />
<double_size value="8" />
<long_double_size value="16" />
<size_alignment_map>
<entry size="1" alignment="1" />
<entry size="2" alignment="2" />
<entry size="4" alignment="4" />
<entry size="8" alignment="8" />
<entry size="16" alignment="16" />
</size_alignment_map>
</data_organization>
<global>
<range space="ram"/>
@ -50,33 +70,49 @@
<pentry minsize="1" maxsize="8" metatype="float" extension="float">
<register name="f13"/>
</pentry>
<pentry minsize="1" maxsize="8">
<pentry minsize="1" maxsize="8" extension="inttype">
<register name="r3"/>
</pentry>
<pentry minsize="1" maxsize="8">
<pentry minsize="1" maxsize="8" extension="inttype">
<register name="r4"/>
</pentry>
<pentry minsize="1" maxsize="8">
<pentry minsize="1" maxsize="8" extension="inttype">
<register name="r5"/>
</pentry>
<pentry minsize="1" maxsize="8">
<pentry minsize="1" maxsize="8" extension="inttype">
<register name="r6"/>
</pentry>
<pentry minsize="1" maxsize="8">
<pentry minsize="1" maxsize="8" extension="inttype">
<register name="r7"/>
</pentry>
<pentry minsize="1" maxsize="8">
<pentry minsize="1" maxsize="8" extension="inttype">
<register name="r8"/>
</pentry>
<pentry minsize="1" maxsize="8">
<pentry minsize="1" maxsize="8" extension="inttype">
<register name="r9"/>
</pentry>
<pentry minsize="1" maxsize="8">
<pentry minsize="1" maxsize="8" extension="inttype">
<register name="r10"/>
</pentry>
<pentry minsize="1" maxsize="500" align="8">
<addr offset="112" space="stack"/>
</pentry>
<rule>
<datatype name="homogeneous-float-aggregate" maxprimitives="1"/>
<join storage="float"/>
<extra_stack afterstorage="general" afterbytes="64"/>
<consume_extra storage="general"/>
</rule>
<rule>
<datatype name="float"/>
<join storage="float"/> <!-- The join is NOT aligned -->
<extra_stack afterstorage="general" afterbytes="64"/>
<consume_extra storage="general"/>
</rule>
<rule>
<datatype name="any"/>
<join align="true"/> <!-- The join IS aligned -->
</rule>
</input>
<output>
<pentry minsize="1" maxsize="8" metatype="float" extension="float">
@ -85,6 +121,14 @@
<pentry minsize="1" maxsize="8" extension="inttype">
<register name="r3"/>
</pentry>
<rule>
<datatype name="struct"/>
<convert_to_ptr/>
</rule>
<rule>
<datatype name="union"/>
<convert_to_ptr/>
</rule>
</output>
<unaffected>
<register name="r14"/>
@ -109,7 +153,32 @@
<!-- In cases where r2 does change, we assume it will get restored -->
<register name="r2"/>
<register name="r2Save"/>
<register name="f14"/>
<register name="f15"/>
<register name="f16"/>
<register name="f17"/>
<register name="f18"/>
<register name="f19"/>
<register name="f20"/>
<register name="f21"/>
<register name="f22"/>
<register name="f23"/>
<register name="f24"/>
<register name="f25"/>
<register name="f26"/>
<register name="f27"/>
<register name="f28"/>
<register name="f29"/>
<register name="f30"/>
<register name="f31"/>
<register name="cr2"/>
<register name="cr3"/>
<register name="cr4"/>
</unaffected>
<killedbycall>
<register name="r3"/>
<register name="f1"/>
</killedbycall>
<pcode inject="uponreturn">
<body>
# Inject pcode when returning from a function call to place the r2Save