mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 11:42:57 +01:00
Params are not being generated as static globals now. The caller passes them onto the callee's stack directly and the callee loads the argvals from its own stack. Clang generated frameindexes validatd by recalculating the stack as if all frameindexes represent 1-byte slots.
llvm-svn: 68327
This commit is contained in:
parent
09cab2de98
commit
1555a0a503
@ -335,6 +335,7 @@ bool PIC16AsmPrinter::doFinalization(Module &M) {
|
|||||||
void PIC16AsmPrinter::emitFunctionData(MachineFunction &MF) {
|
void PIC16AsmPrinter::emitFunctionData(MachineFunction &MF) {
|
||||||
const Function *F = MF.getFunction();
|
const Function *F = MF.getFunction();
|
||||||
std::string FuncName = Mang->getValueName(F);
|
std::string FuncName = Mang->getValueName(F);
|
||||||
|
MachineFrameInfo *MFI= MF.getFrameInfo();
|
||||||
Module *M = const_cast<Module *>(F->getParent());
|
Module *M = const_cast<Module *>(F->getParent());
|
||||||
const TargetData *TD = TM.getTargetData();
|
const TargetData *TD = TM.getTargetData();
|
||||||
unsigned FrameSize = 0;
|
unsigned FrameSize = 0;
|
||||||
@ -346,15 +347,30 @@ void PIC16AsmPrinter::emitFunctionData(MachineFunction &MF) {
|
|||||||
SectionFlags::Writeable);
|
SectionFlags::Writeable);
|
||||||
SwitchToSection(fDataSection);
|
SwitchToSection(fDataSection);
|
||||||
|
|
||||||
//Emit function return value.
|
|
||||||
O << CurrentFnName << ".retval:\n";
|
// Emit function frame label
|
||||||
|
O << CurrentFnName << ".frame:\n";
|
||||||
|
|
||||||
const Type *RetType = F->getReturnType();
|
const Type *RetType = F->getReturnType();
|
||||||
unsigned RetSize = 0;
|
unsigned RetSize = 0;
|
||||||
if (RetType->getTypeID() != Type::VoidTyID)
|
if (RetType->getTypeID() != Type::VoidTyID)
|
||||||
RetSize = TD->getTypePaddedSize(RetType);
|
RetSize = TD->getTypePaddedSize(RetType);
|
||||||
|
|
||||||
// Emit function arguments.
|
//Emit function return value space
|
||||||
O << CurrentFnName << ".args:\n";
|
if(RetSize > 0)
|
||||||
|
O << CurrentFnName << ".retval RES " << RetSize << "\n";
|
||||||
|
else
|
||||||
|
O << CurrentFnName << ".retval:\n";
|
||||||
|
|
||||||
|
// Emit variable to hold the space for function arguments
|
||||||
|
unsigned ArgSize = 0;
|
||||||
|
for (Function::const_arg_iterator argi = F->arg_begin(),
|
||||||
|
arge = F->arg_end(); argi != arge ; ++argi) {
|
||||||
|
const Type *Ty = argi->getType();
|
||||||
|
ArgSize += TD->getTypePaddedSize(Ty);
|
||||||
|
}
|
||||||
|
O << CurrentFnName << ".args RES " << ArgSize << "\n";
|
||||||
|
|
||||||
// Emit the function variables.
|
// Emit the function variables.
|
||||||
|
|
||||||
// In PIC16 all the function arguments and local variables are global.
|
// In PIC16 all the function arguments and local variables are global.
|
||||||
@ -382,34 +398,15 @@ void PIC16AsmPrinter::emitFunctionData(MachineFunction &MF) {
|
|||||||
O << VarName << " RES " << Size << "\n";
|
O << VarName << " RES " << Size << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return value can not overlap with temp data, becasue a temp slot
|
|
||||||
// may be read/written after a return value is calculated and saved
|
|
||||||
// within the function.
|
|
||||||
if (RetSize > FrameSize)
|
|
||||||
O << CurrentFnName << ".dummy" << " RES " << (RetSize - FrameSize) << "\n";
|
|
||||||
|
|
||||||
emitFunctionTempData(MF, FrameSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PIC16AsmPrinter::emitFunctionTempData(MachineFunction &MF,
|
|
||||||
unsigned &FrameSize) {
|
|
||||||
// Emit temporary variables.
|
|
||||||
MachineFrameInfo *FrameInfo = MF.getFrameInfo();
|
|
||||||
if (FrameInfo->hasStackObjects()) {
|
|
||||||
int indexBegin = FrameInfo->getObjectIndexBegin();
|
|
||||||
int indexEnd = FrameInfo->getObjectIndexEnd();
|
|
||||||
|
|
||||||
|
// Emit the variable to hold the space for temporary locations
|
||||||
|
// in function frame.
|
||||||
|
if (MFI->hasStackObjects()) {
|
||||||
|
int indexBegin = MFI->getObjectIndexBegin();
|
||||||
|
int indexEnd = MFI->getObjectIndexEnd();
|
||||||
if (indexBegin < indexEnd) {
|
if (indexBegin < indexEnd) {
|
||||||
FrameSize += indexEnd - indexBegin;
|
int TempSize = indexEnd - indexBegin;
|
||||||
O << CurrentFnName << ".tmp RES"<< " "
|
O << CurrentFnName << ".tmp RES " << TempSize <<"\n";
|
||||||
<<indexEnd - indexBegin <<"\n";
|
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
while (indexBegin < indexEnd) {
|
|
||||||
O << CurrentFnName << "_tmp_" << indexBegin << " " << "RES"<< " "
|
|
||||||
<< 1 << "\n" ;
|
|
||||||
indexBegin++;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,6 @@ namespace llvm {
|
|||||||
void EmitUnInitData (Module &M);
|
void EmitUnInitData (Module &M);
|
||||||
void EmitRomData (Module &M);
|
void EmitRomData (Module &M);
|
||||||
void emitFunctionData(MachineFunction &MF);
|
void emitFunctionData(MachineFunction &MF);
|
||||||
void emitFunctionTempData(MachineFunction &MF, unsigned &FrameSize);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool doInitialization(Module &M);
|
bool doInitialization(Module &M);
|
||||||
|
@ -244,6 +244,7 @@ const char *PIC16TargetLowering::getTargetNodeName(unsigned Opcode) const {
|
|||||||
case PIC16ISD::MTHI: return "PIC16ISD::MTHI";
|
case PIC16ISD::MTHI: return "PIC16ISD::MTHI";
|
||||||
case PIC16ISD::Banksel: return "PIC16ISD::Banksel";
|
case PIC16ISD::Banksel: return "PIC16ISD::Banksel";
|
||||||
case PIC16ISD::PIC16Load: return "PIC16ISD::PIC16Load";
|
case PIC16ISD::PIC16Load: return "PIC16ISD::PIC16Load";
|
||||||
|
case PIC16ISD::PIC16LdArg: return "PIC16ISD::PIC16LdArg";
|
||||||
case PIC16ISD::PIC16LdWF: return "PIC16ISD::PIC16LdWF";
|
case PIC16ISD::PIC16LdWF: return "PIC16ISD::PIC16LdWF";
|
||||||
case PIC16ISD::PIC16Store: return "PIC16ISD::PIC16Store";
|
case PIC16ISD::PIC16Store: return "PIC16ISD::PIC16Store";
|
||||||
case PIC16ISD::PIC16StWF: return "PIC16ISD::PIC16StWF";
|
case PIC16ISD::PIC16StWF: return "PIC16ISD::PIC16StWF";
|
||||||
@ -503,13 +504,24 @@ PIC16TargetLowering::LegalizeFrameIndex(SDValue Op, SelectionDAG &DAG,
|
|||||||
|
|
||||||
MachineFunction &MF = DAG.getMachineFunction();
|
MachineFunction &MF = DAG.getMachineFunction();
|
||||||
const Function *Func = MF.getFunction();
|
const Function *Func = MF.getFunction();
|
||||||
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
const std::string Name = Func->getName();
|
const std::string Name = Func->getName();
|
||||||
|
|
||||||
char *tmpName = new char [strlen(Name.c_str()) + 8];
|
char *tmpName = new char [strlen(Name.c_str()) + 8];
|
||||||
sprintf(tmpName, "%s.args", Name.c_str());
|
sprintf(tmpName, "%s.frame", Name.c_str());
|
||||||
ES = DAG.getTargetExternalSymbol(tmpName, MVT::i8);
|
ES = DAG.getTargetExternalSymbol(tmpName, MVT::i8);
|
||||||
FrameIndexSDNode *FR = dyn_cast<FrameIndexSDNode>(Op);
|
FrameIndexSDNode *FR = dyn_cast<FrameIndexSDNode>(Op);
|
||||||
Offset = FR->getIndex();
|
|
||||||
|
// FrameIndices are not stack offsets. But they represent the request
|
||||||
|
// for space on stack. That space requested may be more than one byte.
|
||||||
|
// Therefore, to calculate the stack offset that a FrameIndex aligns
|
||||||
|
// with, we need to traverse all the FrameIndices available earlier in
|
||||||
|
// the list and add their requested size.
|
||||||
|
unsigned FIndex = FR->getIndex();
|
||||||
|
Offset = 0;
|
||||||
|
for (unsigned i=0; i<FIndex ; ++i) {
|
||||||
|
Offset += MFI->getObjectSize(i);
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -810,7 +822,7 @@ SDValue PIC16TargetLowering::ConvertToMemOperand(SDValue Op,
|
|||||||
const Function *Func = MF.getFunction();
|
const Function *Func = MF.getFunction();
|
||||||
const std::string FuncName = Func->getName();
|
const std::string FuncName = Func->getName();
|
||||||
|
|
||||||
char *tmpName = new char [strlen(FuncName.c_str()) + 6];
|
char *tmpName = new char [strlen(FuncName.c_str()) + 8];
|
||||||
|
|
||||||
// Put the value on stack.
|
// Put the value on stack.
|
||||||
// Get a stack slot index and convert to es.
|
// Get a stack slot index and convert to es.
|
||||||
@ -938,11 +950,41 @@ PIC16TargetLowering::LowerCallReturn(SDValue Op, SDValue Chain,
|
|||||||
}
|
}
|
||||||
|
|
||||||
SDValue PIC16TargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG) {
|
SDValue PIC16TargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG) {
|
||||||
//int NumOps = Op.getNode()->getNumOperands();
|
SDValue Chain = Op.getOperand(0);
|
||||||
|
DebugLoc dl = Op.getDebugLoc();
|
||||||
|
|
||||||
// For default cases LLVM returns the value on the function frame
|
if (Op.getNumOperands() == 1) // return void
|
||||||
// So let LLVM do this for all the cases other than character
|
return Op;
|
||||||
return Op;
|
|
||||||
|
// return should have odd number of operands
|
||||||
|
if ((Op.getNumOperands() % 2) == 0 ) {
|
||||||
|
assert(0 && "Do not know how to return this many arguments!");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Number of values to return
|
||||||
|
unsigned NumRet = (Op.getNumOperands() / 2);
|
||||||
|
|
||||||
|
// Function returns value always on stack with the offset starting
|
||||||
|
// from 0
|
||||||
|
MachineFunction &MF = DAG.getMachineFunction();
|
||||||
|
const Function *F = MF.getFunction();
|
||||||
|
std::string FuncName = F->getName();
|
||||||
|
|
||||||
|
char *tmpName = new char [strlen(FuncName.c_str()) + 8];
|
||||||
|
sprintf(tmpName, "%s.frame", FuncName.c_str());
|
||||||
|
SDVTList VTs = DAG.getVTList (MVT::i8, MVT::Other);
|
||||||
|
SDValue ES = DAG.getTargetExternalSymbol(tmpName, MVT::i8);
|
||||||
|
SDValue BS = DAG.getConstant(1, MVT::i8);
|
||||||
|
SDValue RetVal;
|
||||||
|
for(unsigned i=0;i<NumRet; ++i) {
|
||||||
|
RetVal = Op.getNode()->getOperand(2*i + 1);
|
||||||
|
Chain = DAG.getNode (PIC16ISD::PIC16Store, dl, MVT::Other, Chain, RetVal,
|
||||||
|
ES, BS,
|
||||||
|
DAG.getConstant (i, MVT::i8));
|
||||||
|
|
||||||
|
}
|
||||||
|
return DAG.getNode(ISD::RET, dl, MVT::Other, Chain);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDValue PIC16TargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
|
SDValue PIC16TargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
|
||||||
@ -1164,13 +1206,26 @@ SDValue PIC16TargetLowering::LowerSUB(SDValue Op, SelectionDAG &DAG) {
|
|||||||
SDValue PIC16TargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op,
|
SDValue PIC16TargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op,
|
||||||
SelectionDAG &DAG) {
|
SelectionDAG &DAG) {
|
||||||
SmallVector<SDValue, 8> ArgValues;
|
SmallVector<SDValue, 8> ArgValues;
|
||||||
unsigned NumArgs = Op.getNumOperands() - 3;
|
unsigned NumArgs = Op.getNode()->getNumValues()-1;
|
||||||
DebugLoc dl = Op.getDebugLoc();
|
DebugLoc dl = Op.getDebugLoc();
|
||||||
|
SDValue Chain = Op.getOperand(0); // Formal arguments' chain
|
||||||
|
|
||||||
// Creating UNDEF nodes to meet the requirement of MERGE_VALUES node.
|
MachineFunction &MF = DAG.getMachineFunction();
|
||||||
for(unsigned i = 0 ; i<NumArgs ; i++) {
|
//const TargetData *TD = getTargetData();
|
||||||
SDValue TempNode = DAG.getUNDEF(Op.getNode()->getValueType(i));
|
const Function *F = MF.getFunction();
|
||||||
ArgValues.push_back(TempNode);
|
std::string FuncName = F->getName();
|
||||||
|
|
||||||
|
char *tmpName = new char [strlen(FuncName.c_str()) + 6];
|
||||||
|
sprintf(tmpName, "%s.args", FuncName.c_str());
|
||||||
|
SDVTList VTs = DAG.getVTList (MVT::i8, MVT::Other);
|
||||||
|
SDValue ES = DAG.getTargetExternalSymbol(tmpName, MVT::i8);
|
||||||
|
SDValue BS = DAG.getConstant(1, MVT::i8);
|
||||||
|
for (unsigned i=0; i<NumArgs ; ++i) {
|
||||||
|
SDValue Offset = DAG.getConstant(i, MVT::i8);
|
||||||
|
SDValue PICLoad = DAG.getNode(PIC16ISD::PIC16LdArg, dl, VTs, Chain, ES, BS,
|
||||||
|
Offset);
|
||||||
|
Chain = getChain(PICLoad);
|
||||||
|
ArgValues.push_back(PICLoad);
|
||||||
}
|
}
|
||||||
|
|
||||||
ArgValues.push_back(Op.getOperand(0));
|
ArgValues.push_back(Op.getOperand(0));
|
||||||
@ -1191,10 +1246,33 @@ PerformPIC16LoadCombine(SDNode *N, DAGCombinerInfo &DCI) const {
|
|||||||
return SDValue();
|
return SDValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For all the functions with arguments some STORE nodes are generated
|
||||||
|
// that store the argument on the frameindex. However in PIC16 the arguments
|
||||||
|
// are passed on stack only. Therefore these STORE nodes are redundant.
|
||||||
|
// To remove these STORE nodes will be removed in PerformStoreCombine
|
||||||
|
//
|
||||||
|
// Currently this function is doint nothing and will be updated for removing
|
||||||
|
// unwanted store operations
|
||||||
|
SDValue PIC16TargetLowering::
|
||||||
|
PerformStoreCombine(SDNode *N, DAGCombinerInfo &DCI) const {
|
||||||
|
SelectionDAG &DAG = DCI.DAG;
|
||||||
|
SDValue Chain;
|
||||||
|
return SDValue(N, 0);
|
||||||
|
/*
|
||||||
|
// Storing an undef value is of no use, so remove it
|
||||||
|
if (isStoringUndef(N, Chain, DAG)) {
|
||||||
|
return Chain; // remove the store and return the chain
|
||||||
|
}
|
||||||
|
//else everything is ok.
|
||||||
|
return SDValue(N, 0);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
SDValue PIC16TargetLowering::PerformDAGCombine(SDNode *N,
|
SDValue PIC16TargetLowering::PerformDAGCombine(SDNode *N,
|
||||||
DAGCombinerInfo &DCI) const {
|
DAGCombinerInfo &DCI) const {
|
||||||
switch (N->getOpcode()) {
|
switch (N->getOpcode()) {
|
||||||
|
case ISD::STORE:
|
||||||
|
return PerformStoreCombine(N, DCI);
|
||||||
case PIC16ISD::PIC16Load:
|
case PIC16ISD::PIC16Load:
|
||||||
return PerformPIC16LoadCombine(N, DCI);
|
return PerformPIC16LoadCombine(N, DCI);
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,10 @@ namespace llvm {
|
|||||||
Lo, // Low 8-bits of GlobalAddress.
|
Lo, // Low 8-bits of GlobalAddress.
|
||||||
Hi, // High 8-bits of GlobalAddress.
|
Hi, // High 8-bits of GlobalAddress.
|
||||||
PIC16Load,
|
PIC16Load,
|
||||||
|
PIC16LdArg, // This is replica of PIC16Load but used to load function
|
||||||
|
// arguments and is being used for facilitating for some
|
||||||
|
// store removal optimizations.
|
||||||
|
|
||||||
PIC16LdWF,
|
PIC16LdWF,
|
||||||
PIC16Store,
|
PIC16Store,
|
||||||
PIC16StWF,
|
PIC16StWF,
|
||||||
@ -103,17 +107,17 @@ namespace llvm {
|
|||||||
|
|
||||||
SDValue ExpandStore(SDNode *N, SelectionDAG &DAG);
|
SDValue ExpandStore(SDNode *N, SelectionDAG &DAG);
|
||||||
SDValue ExpandLoad(SDNode *N, SelectionDAG &DAG);
|
SDValue ExpandLoad(SDNode *N, SelectionDAG &DAG);
|
||||||
//SDValue ExpandAdd(SDNode *N, SelectionDAG &DAG);
|
|
||||||
SDValue ExpandGlobalAddress(SDNode *N, SelectionDAG &DAG);
|
SDValue ExpandGlobalAddress(SDNode *N, SelectionDAG &DAG);
|
||||||
SDValue ExpandExternalSymbol(SDNode *N, SelectionDAG &DAG);
|
SDValue ExpandExternalSymbol(SDNode *N, SelectionDAG &DAG);
|
||||||
SDValue ExpandFrameIndex(SDNode *N, SelectionDAG &DAG);
|
SDValue ExpandFrameIndex(SDNode *N, SelectionDAG &DAG);
|
||||||
|
|
||||||
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
|
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
|
||||||
SDValue PerformPIC16LoadCombine(SDNode *N, DAGCombinerInfo &DCI) const;
|
SDValue PerformPIC16LoadCombine(SDNode *N, DAGCombinerInfo &DCI) const;
|
||||||
|
SDValue PerformStoreCombine(SDNode *N, DAGCombinerInfo &DCI) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// If the Node is a BUILD_PAIR representing representing an Address
|
// If the Node is a BUILD_PAIR representing a direct Address,
|
||||||
// then this function will return true
|
// then this function will return true.
|
||||||
bool isDirectAddress(const SDValue &Op);
|
bool isDirectAddress(const SDValue &Op);
|
||||||
|
|
||||||
// If the Node is a DirectAddress in ROM_SPACE then this
|
// If the Node is a DirectAddress in ROM_SPACE then this
|
||||||
@ -149,14 +153,14 @@ namespace llvm {
|
|||||||
|
|
||||||
|
|
||||||
// Extending the LIB Call framework of LLVM
|
// Extending the LIB Call framework of LLVM
|
||||||
// To hold the names of PIC16Libcalls
|
// to hold the names of PIC16Libcalls.
|
||||||
const char *PIC16LibcallNames[PIC16ISD::PIC16UnknownCall];
|
const char *PIC16LibcallNames[PIC16ISD::PIC16UnknownCall];
|
||||||
|
|
||||||
// To set and retrieve the lib call names
|
// To set and retrieve the lib call names.
|
||||||
void setPIC16LibcallName(PIC16ISD::PIC16Libcall Call, const char *Name);
|
void setPIC16LibcallName(PIC16ISD::PIC16Libcall Call, const char *Name);
|
||||||
const char *getPIC16LibcallName(PIC16ISD::PIC16Libcall Call);
|
const char *getPIC16LibcallName(PIC16ISD::PIC16Libcall Call);
|
||||||
|
|
||||||
// Make PIC16 Libcall
|
// Make PIC16 Libcall.
|
||||||
SDValue MakePIC16Libcall(PIC16ISD::PIC16Libcall Call, MVT RetVT,
|
SDValue MakePIC16Libcall(PIC16ISD::PIC16Libcall Call, MVT RetVT,
|
||||||
const SDValue *Ops, unsigned NumOps, bool isSigned,
|
const SDValue *Ops, unsigned NumOps, bool isSigned,
|
||||||
SelectionDAG &DAG, DebugLoc dl);
|
SelectionDAG &DAG, DebugLoc dl);
|
||||||
|
@ -88,8 +88,9 @@ def PIC16StWF : SDNode<"PIC16ISD::PIC16StWF", SDT_PIC16Store,
|
|||||||
[SDNPHasChain, SDNPInFlag, SDNPOutFlag]>;
|
[SDNPHasChain, SDNPInFlag, SDNPOutFlag]>;
|
||||||
|
|
||||||
// Node to match a direct load operation.
|
// Node to match a direct load operation.
|
||||||
def PIC16Load : SDNode<"PIC16ISD::PIC16Load", SDT_PIC16Load, [SDNPHasChain]>;
|
def PIC16Load : SDNode<"PIC16ISD::PIC16Load", SDT_PIC16Load, [SDNPHasChain]>;
|
||||||
def PIC16LdWF : SDNode<"PIC16ISD::PIC16LdWF", SDT_PIC16Load,
|
def PIC16LdArg : SDNode<"PIC16ISD::PIC16LdArg", SDT_PIC16Load, [SDNPHasChain]>;
|
||||||
|
def PIC16LdWF : SDNode<"PIC16ISD::PIC16LdWF", SDT_PIC16Load,
|
||||||
[SDNPHasChain, SDNPInFlag, SDNPOutFlag]>;
|
[SDNPHasChain, SDNPInFlag, SDNPOutFlag]>;
|
||||||
|
|
||||||
// Node to match PIC16 call
|
// Node to match PIC16 call
|
||||||
@ -267,6 +268,7 @@ def movf : MOVF_INSN<0, tglobaladdr, PIC16Load>;
|
|||||||
|
|
||||||
// Load from an ES.
|
// Load from an ES.
|
||||||
def movf_1 : MOVF_INSN<0, texternalsym, PIC16Load>;
|
def movf_1 : MOVF_INSN<0, texternalsym, PIC16Load>;
|
||||||
|
def movf_1_1 : MOVF_INSN<0, texternalsym, PIC16LdArg>;
|
||||||
|
|
||||||
// Load with InFlag and OutFlag
|
// Load with InFlag and OutFlag
|
||||||
// This is same as movf_1 but has a flag. A flag is required to
|
// This is same as movf_1 but has a flag. A flag is required to
|
||||||
|
Loading…
Reference in New Issue
Block a user