1998-12-04 00:10:47 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
|
|
*
|
1999-11-02 09:38:29 +03:00
|
|
|
* The contents of this file are subject to the Netscape Public
|
|
|
|
* License Version 1.1 (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.mozilla.org/NPL/
|
1998-12-04 00:10:47 +03:00
|
|
|
*
|
1999-11-02 09:38:29 +03:00
|
|
|
* Software distributed under the License is distributed on an "AS
|
|
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
|
|
* implied. See the License for the specific language governing
|
|
|
|
* rights and limitations under the License.
|
1998-12-04 00:10:47 +03:00
|
|
|
*
|
1999-11-02 09:38:29 +03:00
|
|
|
* The Original Code is mozilla.org code.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is Netscape
|
1998-12-04 00:10:47 +03:00
|
|
|
* Communications Corporation. Portions created by Netscape are
|
1999-11-02 09:38:29 +03:00
|
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
|
|
|
* Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
1998-12-04 00:10:47 +03:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "SparcSunOSEmitter.h"
|
|
|
|
#include "SparcInstruction.h"
|
|
|
|
#include "ControlNodes.h"
|
|
|
|
#include "sparc-sunos.nad.burg.h"
|
|
|
|
|
|
|
|
#define BINARY_PRIMITIVE_I(inRuleKind, inOp) \
|
|
|
|
case inRuleKind: \
|
|
|
|
emit_Insn_I(inPrimitive, inOp); \
|
|
|
|
break;
|
|
|
|
|
|
|
|
#define BINARY_PRIMITIVEI_I(inRuleKind, inOp) \
|
|
|
|
case inRuleKind: \
|
|
|
|
emit_InsnI_I(inPrimitive, inOp); \
|
|
|
|
break;
|
|
|
|
|
|
|
|
#define UNDEFINED_RULE(inRuleKind) \
|
|
|
|
case inRuleKind: \
|
|
|
|
assert(false); \
|
|
|
|
break;
|
|
|
|
|
|
|
|
#define BINARY_PRIMITIVE_SET(inRuleRoot, inOp) \
|
|
|
|
BINARY_PRIMITIVE_I(inRuleRoot##_I, inOp); \
|
|
|
|
UNDEFINED_RULE(inRuleRoot##_L); \
|
|
|
|
BINARY_PRIMITIVEI_I(inRuleRoot##I_I, inOp); \
|
|
|
|
UNDEFINED_RULE(inRuleRoot##I_L);
|
|
|
|
|
|
|
|
void SparcSunOSEmitter::
|
|
|
|
emitPrimitive(Primitive& inPrimitive, NamedRule inRule)
|
|
|
|
{
|
|
|
|
switch (inRule)
|
|
|
|
{
|
|
|
|
case emConst_I:
|
|
|
|
emit_Const_I(inPrimitive);
|
|
|
|
break;
|
|
|
|
case emArg_I:
|
|
|
|
case emArg_L:
|
|
|
|
case emArg_F:
|
|
|
|
case emArg_D:
|
|
|
|
case emArg_A:
|
|
|
|
assert(false);
|
|
|
|
break;
|
|
|
|
case emResult_M:
|
|
|
|
case emArg_M:
|
|
|
|
break;
|
|
|
|
case emResult_I:
|
|
|
|
{
|
|
|
|
VirtualRegister* returnVr;
|
|
|
|
if (inPrimitive.nthInputIsConstant(0))
|
|
|
|
{
|
|
|
|
returnVr = &genLoadConstant(inPrimitive, inPrimitive.nthInputConstant(0).i);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SparcInsn& copyInsn = *new(mPool) SparcInsn(&inPrimitive, mPool, siOr, saRZR);
|
|
|
|
|
|
|
|
returnVr = &defineTemporary(copyInsn, 0);
|
|
|
|
useProducer(inPrimitive.nthInputVariable(0), copyInsn, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
returnVr->precolorRegister(registerNumberToColor[o0]);
|
|
|
|
|
|
|
|
InsnExternalUse& externalUse = *new(mPool) InsnExternalUse(&inPrimitive);
|
|
|
|
useTemporaryVR(externalUse, *returnVr, 0);
|
|
|
|
inPrimitive.setInstructionRoot(&externalUse);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case emIfLt:
|
|
|
|
emit_B(inPrimitive, scL);
|
|
|
|
break;
|
|
|
|
case emIfULt:
|
|
|
|
emit_B(inPrimitive, scLu);
|
|
|
|
break;
|
|
|
|
case emIfEq:
|
|
|
|
case emIfUEq:
|
|
|
|
emit_B(inPrimitive, scE);
|
|
|
|
break;
|
|
|
|
case emIfLe:
|
|
|
|
emit_B(inPrimitive, scLe);
|
|
|
|
break;
|
|
|
|
case emIfULe:
|
|
|
|
emit_B(inPrimitive, scLeu);
|
|
|
|
break;
|
|
|
|
case emIfGt:
|
|
|
|
emit_B(inPrimitive, scG);
|
|
|
|
break;
|
|
|
|
case emIfUGt:
|
|
|
|
emit_B(inPrimitive, scGu);
|
|
|
|
break;
|
|
|
|
case emIfLgt:
|
|
|
|
case emIfNe:
|
|
|
|
emit_B(inPrimitive, scNe);
|
|
|
|
break;
|
|
|
|
case emIfGe:
|
|
|
|
emit_B(inPrimitive, scGe);
|
|
|
|
break;
|
|
|
|
case emIfUGe:
|
|
|
|
emit_B(inPrimitive, scGeu);
|
|
|
|
break;
|
|
|
|
case emIfOrd:
|
|
|
|
case emIfUnord:
|
|
|
|
assert(false); // Shouldn't happen with int edges...
|
|
|
|
break;
|
|
|
|
BINARY_PRIMITIVE_SET(emAnd, siAnd);
|
|
|
|
BINARY_PRIMITIVE_SET(emOr, siOr );
|
|
|
|
BINARY_PRIMITIVE_SET(emXor, siXor);
|
|
|
|
BINARY_PRIMITIVE_SET(emAdd, siAdd);
|
|
|
|
case emAdd_A:
|
|
|
|
emit_Insn_I(inPrimitive, siAdd);
|
|
|
|
break;
|
|
|
|
case emAddI_A:
|
|
|
|
emit_InsnI_I(inPrimitive, siAdd);
|
|
|
|
break;
|
|
|
|
BINARY_PRIMITIVE_SET(emMul, siSMul);
|
|
|
|
case emDivI_I:
|
|
|
|
emit_DivI_I(inPrimitive);
|
|
|
|
break;
|
|
|
|
case emModE_I:
|
|
|
|
emit_ModE_I(inPrimitive);
|
|
|
|
break;
|
|
|
|
case emShlI_I:
|
|
|
|
emit_InsnI_I(inPrimitive, siSll);
|
|
|
|
break;
|
|
|
|
case emChkNull:
|
|
|
|
emit_ChkNull(inPrimitive);
|
|
|
|
break;
|
|
|
|
case emLimitR:
|
|
|
|
emit_LimitR(inPrimitive);
|
|
|
|
break;
|
|
|
|
case emLimit:
|
|
|
|
emit_Limit(inPrimitive);
|
|
|
|
break;
|
|
|
|
case emLdC_IRegisterIndirect:
|
|
|
|
emit_LdC_IRegisterIndirect(inPrimitive);
|
|
|
|
break;
|
|
|
|
case emLd_IRegisterIndirect:
|
|
|
|
emit_Ld_IRegisterIndirect(inPrimitive);
|
|
|
|
break;
|
|
|
|
case emLdC_I:
|
|
|
|
fprintf(stdout, "*** should emit emLdC_I\n");
|
|
|
|
//genLoadIZero(inPrimitive, pfConstant);
|
|
|
|
break;
|
|
|
|
case emLd_I:
|
|
|
|
fprintf(stdout, "*** should emit emLd_I\n");
|
|
|
|
//genLoadIZero(inPrimitive, 0);
|
|
|
|
break;
|
|
|
|
case emSt_I:
|
|
|
|
fprintf(stdout, "*** should emit emSt_I\n");
|
|
|
|
//{
|
|
|
|
//StoreNoUpdateD& newInsn = *new(mPool) StoreNoUpdateD(&inPrimitive, mPool, dfStw, 0, 0);
|
|
|
|
//newInsn.standardUseDefine(*this);
|
|
|
|
//}
|
|
|
|
break;
|
|
|
|
case emStI_I:
|
|
|
|
fprintf(stdout, "*** should emit emStI_I\n");
|
|
|
|
//emit_StI_I(inPrimitive);
|
|
|
|
break;
|
|
|
|
case emStI_IRegisterIndirect:
|
|
|
|
emit_StI_IRegisterIndirect(inPrimitive);
|
|
|
|
break;
|
|
|
|
case emSt_IRegisterIndirect:
|
|
|
|
emit_St_IRegisterIndirect(inPrimitive);
|
|
|
|
break;
|
|
|
|
case emCallI_I:
|
|
|
|
case emCallI_L:
|
|
|
|
case emCallI_F:
|
|
|
|
case emCallI_D:
|
|
|
|
case emCallI_P:
|
|
|
|
fprintf(stdout, "*** should emit emCallI_P\n");
|
|
|
|
//emit_Call(inPrimitive);
|
|
|
|
break;
|
|
|
|
case emCmp_I:
|
|
|
|
emit_Cmp_I(inPrimitive);
|
|
|
|
break;
|
|
|
|
case emCmpI_I:
|
|
|
|
emit_CmpI_I(inPrimitive);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
//assert(false)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SparcSunOSEmitter::
|
|
|
|
emit_Const_I(Primitive& inPrimitive)
|
|
|
|
{
|
|
|
|
int32 constI = (*static_cast<const PrimConst *>(&inPrimitive)).value.i;
|
|
|
|
if ((constI >= -4096) && (constI <= 4095))
|
|
|
|
{
|
|
|
|
SparcInsn& newInsn = *new(mPool) SparcInsn(&inPrimitive, mPool, siOr, constI ? saZIR : saZZR, constI & 0x1fff);
|
|
|
|
defineProducer(inPrimitive, newInsn, 0);
|
|
|
|
}
|
|
|
|
else if ((constI & 0x1fff) == 0)
|
|
|
|
{
|
|
|
|
// FIXME
|
|
|
|
assert(0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// FIXME
|
|
|
|
assert(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SparcSunOSEmitter::
|
|
|
|
emit_InsnI_I(Primitive& inPrimitive, SparcInstructionKind kind)
|
|
|
|
{
|
|
|
|
int32 constI = inPrimitive.nthInputConstant(1).i;
|
|
|
|
if ((constI >= -4096) && (constI <= 4095))
|
|
|
|
{
|
|
|
|
SparcInsn& newInsn = *new(mPool) SparcInsn(&inPrimitive, mPool, kind, constI ? saRIR : saRZR, constI & 0x1fff);
|
|
|
|
newInsn.standardUseDefine(*this);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
assert(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SparcSunOSEmitter::
|
|
|
|
emit_Insn_I(Primitive& inPrimitive, SparcInstructionKind kind)
|
|
|
|
{
|
|
|
|
SparcInsn& newInsn = *new(mPool) SparcInsn(&inPrimitive, mPool, kind, saRRR);
|
|
|
|
newInsn.standardUseDefine(*this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SparcSunOSEmitter::
|
|
|
|
emit_Cmp_I(Primitive& inPrimitive)
|
|
|
|
{
|
|
|
|
SparcCmp& newInsn = *new(mPool) SparcCmp(&inPrimitive, mPool, saRR);
|
|
|
|
newInsn.standardUseDefine(*this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SparcSunOSEmitter::
|
|
|
|
emit_CmpI_I(Primitive& inPrimitive)
|
|
|
|
{
|
|
|
|
int32 constI = inPrimitive.nthInputConstant(1).i;
|
|
|
|
if ((constI >= -4096) && (constI <= 4095))
|
|
|
|
{
|
|
|
|
SparcCmp& newInsn = *new(mPool) SparcCmp(&inPrimitive, mPool, constI ? saRI : saRZ, constI & 0x1fff);
|
|
|
|
newInsn.standardUseDefine(*this);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
assert(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SparcSunOSEmitter::
|
|
|
|
emit_B(Primitive& inPrimitive, SparcConditionKind cond)
|
|
|
|
{
|
|
|
|
ControlIf& controlIf = ControlIf::cast(*inPrimitive.getContainer());
|
|
|
|
SparcBranch& newInsn = *new(mPool) SparcBranch(&inPrimitive, mPool, *(controlIf.getTrueIfEdge().target), cond, true);
|
|
|
|
newInsn.standardUseDefine(*this);
|
|
|
|
}
|
|
|
|
|
|
|
|
Instruction& SparcSunOSEmitter::
|
|
|
|
emitAbsoluteBranch(DataNode& inDataNode, ControlNode& inTarget)
|
|
|
|
{
|
|
|
|
SparcBranch& newInsn = *new(mPool) SparcBranch(&inDataNode, mPool, inTarget, scA, true);
|
|
|
|
return (newInsn);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SparcSunOSEmitter::
|
|
|
|
emitArguments(ControlBegin& inBeginNode)
|
|
|
|
{
|
|
|
|
uint32 curParamWords; // number of words of argument space used
|
|
|
|
uint32 curFloatingPointArg; // number of floating point arguments
|
|
|
|
|
|
|
|
InsnExternalDefine& defineInsn = *new(mPool) InsnExternalDefine(&inBeginNode.arguments[0], mPool, inBeginNode.nArguments * 2);
|
|
|
|
|
|
|
|
uint32 curArgIdx; // current index into the arguments in the ControlBegin
|
|
|
|
|
|
|
|
curParamWords = 0;
|
|
|
|
curFloatingPointArg = 0;
|
|
|
|
for (curArgIdx = 0; curArgIdx < inBeginNode.nArguments && curParamWords < 6; curArgIdx++)
|
|
|
|
{
|
|
|
|
PrimArg& curArg = inBeginNode.arguments[curArgIdx];
|
|
|
|
|
|
|
|
switch (curArg.getOperation())
|
|
|
|
{
|
|
|
|
case poArg_I:
|
|
|
|
case poArg_A:
|
|
|
|
{
|
|
|
|
SparcInsn& copyInsn = *new(mPool) SparcInsn(&curArg, mPool, siOr, saRZR);
|
|
|
|
|
|
|
|
// hook up this vr to the external define FIX-ME
|
|
|
|
VirtualRegister& inputVr = defineTemporary(defineInsn, curArgIdx);
|
|
|
|
inputVr.precolorRegister(registerNumberToColor[i0+curParamWords]);
|
|
|
|
|
|
|
|
// emit the copy
|
|
|
|
useTemporaryVR(copyInsn, inputVr, 0);
|
|
|
|
defineProducer(curArg, copyInsn, 0);
|
|
|
|
|
|
|
|
curParamWords++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case poArg_L:
|
|
|
|
assert(false);
|
|
|
|
|
|
|
|
case poArg_F:
|
|
|
|
assert(false);
|
|
|
|
|
|
|
|
case poArg_D:
|
|
|
|
assert(false);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case poArg_M:
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
assert(false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: emit the load for the arguments on the stack
|
|
|
|
|
|
|
|
// continue counting from before
|
|
|
|
// make all the rest of the defines as type none
|
|
|
|
for (;curArgIdx < inBeginNode.nArguments * 2; curArgIdx++)
|
|
|
|
{
|
|
|
|
defineInsn.getInstructionDefineBegin()[curArgIdx].kind = udNone;
|
|
|
|
}
|
|
|
|
// check for half stack half reg case
|
|
|
|
}
|
|
|
|
|
|
|
|
Instruction& SparcSunOSEmitter::
|
|
|
|
emitCopy(DataNode& inDataNode, VirtualRegister& fromVr, VirtualRegister& toVr)
|
|
|
|
{
|
|
|
|
SparcInsn& newInsn = *new(mPool) SparcInsn(&inDataNode, mPool, siOr, saRZR);
|
|
|
|
newInsn.addUse(0, fromVr);
|
|
|
|
newInsn.addDefine(0, toVr);
|
|
|
|
#if DEBUG
|
|
|
|
toVr.setDefineInstruction(newInsn);
|
|
|
|
#endif
|
|
|
|
return (newInsn);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SparcSunOSEmitter::
|
|
|
|
emit_DivI_I(Primitive& inPrimitive)
|
|
|
|
{
|
|
|
|
Value& immediate = inPrimitive.nthInputConstant(1);
|
|
|
|
if(isPowerOfTwo(immediate.i))
|
|
|
|
{
|
|
|
|
uint8 shiftBy = 31 - leadingZeros(immediate.i);
|
|
|
|
|
|
|
|
SparcInsn& shiftRightL = *new(mPool) SparcInsn(&inPrimitive, mPool, siSrl, saRIR, 31);
|
|
|
|
useProducer(inPrimitive.nthInputVariable(0), shiftRightL, 0);
|
|
|
|
VirtualRegister& tempVr = defineTemporary(shiftRightL, 0);
|
|
|
|
inPrimitive.setInstructionRoot(&shiftRightL);
|
|
|
|
|
|
|
|
SparcInsn& addInsn = *new(mPool) SparcInsn(&inPrimitive, mPool, siAdd, saRRR);
|
|
|
|
useProducer(inPrimitive.nthInputVariable(0), addInsn, 0);
|
|
|
|
useTemporaryVR(addInsn, tempVr, 1);
|
|
|
|
redefineTemporary(addInsn, tempVr, 0);
|
|
|
|
|
|
|
|
SparcInsn& shiftRight = *new(mPool) SparcInsn(&inPrimitive, mPool, siSra, saRIR, shiftBy);
|
|
|
|
useTemporaryVR(shiftRight, tempVr, 0);
|
|
|
|
defineProducer(inPrimitive, shiftRight, 0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
// FIXME: check 0
|
|
|
|
emit_InsnI_I(inPrimitive, siSDiv);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SparcSunOSEmitter::
|
|
|
|
emit_ModE_I(Primitive& inPrimitive)
|
|
|
|
{
|
|
|
|
// Check the divisor != 0
|
|
|
|
SparcCmp& cmpInsn = *new(mPool) SparcCmp(&inPrimitive, mPool, saRZ);
|
|
|
|
useProducer(inPrimitive.nthInputVariable(1), cmpInsn, 0);
|
|
|
|
cmpInsn.addDefine(0, udCond);
|
|
|
|
SparcTrap& trapInsn = *new(mPool) SparcTrap(&inPrimitive, mPool, scE, saRRR /* FIXME */);
|
|
|
|
trapInsn.addUse(0, udCond);
|
|
|
|
trapInsn.getInstructionUseBegin()->setDefiningInstruction(cmpInsn);
|
|
|
|
inPrimitive.setInstructionRoot(&trapInsn);
|
|
|
|
|
|
|
|
SparcInsn& divInsn = *new(mPool) SparcInsn(&inPrimitive, mPool, siSDiv, saRRR);
|
|
|
|
useProducer(inPrimitive.nthInputVariable(0), divInsn, 0);
|
|
|
|
useProducer(inPrimitive.nthInputVariable(1), divInsn, 1);
|
|
|
|
VirtualRegister& tempVr = defineTemporary(divInsn, 0);
|
|
|
|
|
|
|
|
SparcInsn& mullInsn = *new(mPool) SparcInsn(&inPrimitive, mPool, siSMul, saRRR);
|
|
|
|
useProducer(inPrimitive.nthInputVariable(1), mullInsn, 1);
|
|
|
|
useTemporaryVR(mullInsn, tempVr, 0);
|
|
|
|
redefineTemporary(mullInsn, tempVr, 0);
|
|
|
|
|
|
|
|
SparcInsn& subInsn = *new(mPool) SparcInsn(&inPrimitive, mPool, siSub, saRRR);
|
|
|
|
useTemporaryVR(subInsn, tempVr, 0);
|
|
|
|
useProducer(inPrimitive.nthInputVariable(0), subInsn, 1);
|
|
|
|
defineProducer(inPrimitive, subInsn, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SparcSunOSEmitter::
|
|
|
|
emit_ChkNull(Primitive& inPrimitive)
|
|
|
|
{
|
|
|
|
SparcCmp& cmpInsn = *new(mPool) SparcCmp(&inPrimitive, mPool, saRZ);
|
|
|
|
useProducer(inPrimitive.nthInputVariable(0), cmpInsn, 0);
|
|
|
|
cmpInsn.addDefine(0, udCond);
|
|
|
|
|
|
|
|
SparcTrap& trapInsn = *new(mPool) SparcTrap(&inPrimitive, mPool, scE, saRRR /* FIXME */);
|
|
|
|
trapInsn.addUse(0, udCond);
|
|
|
|
trapInsn.getInstructionUseBegin()->setDefiningInstruction(cmpInsn);
|
|
|
|
inPrimitive.setInstructionRoot(&trapInsn);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SparcSunOSEmitter::
|
|
|
|
emit_LimitR(Primitive& inPrimitive)
|
|
|
|
{
|
|
|
|
int32 constI = inPrimitive.nthInputConstant(0).i;
|
|
|
|
if ((constI >= -4096) && (constI <= 4095))
|
|
|
|
{
|
|
|
|
SparcCmp& cmpInsn = *new(mPool) SparcCmp(&inPrimitive, mPool, constI ? saRI : saRZ, constI & 0x1fff);
|
|
|
|
useProducer(inPrimitive.nthInputVariable(1), cmpInsn, 0);
|
|
|
|
cmpInsn.addDefine(0, udCond);
|
|
|
|
|
|
|
|
SparcTrap& trapInsn = *new(mPool) SparcTrap(&inPrimitive, mPool, scLe, saRRR /* FIXME */);
|
|
|
|
trapInsn.addUse(0, udCond);
|
|
|
|
trapInsn.getInstructionUseBegin()->setDefiningInstruction(cmpInsn);
|
|
|
|
inPrimitive.setInstructionRoot(&trapInsn);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
assert(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SparcSunOSEmitter::
|
|
|
|
emit_Limit(Primitive& inPrimitive)
|
|
|
|
{
|
|
|
|
SparcCmp& cmpInsn = *new(mPool) SparcCmp(&inPrimitive, mPool, saRR);
|
|
|
|
useProducer(inPrimitive.nthInputVariable(0), cmpInsn, 0);
|
|
|
|
useProducer(inPrimitive.nthInputVariable(1), cmpInsn, 1);
|
|
|
|
cmpInsn.addDefine(0, udCond);
|
|
|
|
|
|
|
|
SparcTrap& trapInsn = *new(mPool) SparcTrap(&inPrimitive, mPool, scGe, saRRR /* FIXME */);
|
|
|
|
trapInsn.addUse(0, udCond);
|
|
|
|
trapInsn.getInstructionUseBegin()->setDefiningInstruction(cmpInsn);
|
|
|
|
inPrimitive.setInstructionRoot(&trapInsn);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SparcSunOSEmitter::
|
|
|
|
emit_LdC_IRegisterIndirect(Primitive& inPrimitive)
|
|
|
|
{
|
|
|
|
DataNode& immSource = inPrimitive.nthInput(0).getProducer().getNode();
|
|
|
|
|
|
|
|
int32 constI = immSource.nthInputConstant(1).i;
|
|
|
|
if ((constI >= -4096) && (constI <= 4095))
|
|
|
|
{
|
|
|
|
SparcLoadC& newInsn = *new(mPool) SparcLoadC(&inPrimitive, mPool, siLd, saRIR, constI);
|
|
|
|
useProducer(immSource.nthInputVariable(0), newInsn, 0);
|
|
|
|
defineProducer(inPrimitive, newInsn, 0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
assert(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SparcSunOSEmitter::
|
|
|
|
emit_Ld_IRegisterIndirect(Primitive& inPrimitive)
|
|
|
|
{
|
|
|
|
DataNode& immSource = inPrimitive.nthInput(1).getProducer().getNode();
|
|
|
|
|
|
|
|
int32 constI = immSource.nthInputConstant(1).i;
|
|
|
|
|
|
|
|
if ((constI >= -4096) && (constI <= 4095))
|
|
|
|
{
|
|
|
|
SparcLoad& newInsn = *new(mPool) SparcLoad(&inPrimitive, mPool, siLd, saRIR, false, constI);
|
|
|
|
useProducer(inPrimitive.nthInputVariable(0), newInsn, 0); // M to poLd_I
|
|
|
|
useProducer(immSource.nthInputVariable(0), newInsn, 1); // Vint to poAdd_A
|
|
|
|
defineProducer(inPrimitive, newInsn, 0); // Vint from poLd_I
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
assert(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SparcSunOSEmitter::
|
|
|
|
emit_StI_IRegisterIndirect(Primitive& inPrimitive)
|
|
|
|
{
|
|
|
|
SparcStore* storeInsn;
|
|
|
|
|
|
|
|
// load the constant to be stored into constVr
|
|
|
|
VirtualRegister& constVr = genLoadConstant(inPrimitive, inPrimitive.nthInputConstant(2).i);
|
|
|
|
|
|
|
|
// grab the immediate value from the incoming poAddA_I
|
|
|
|
DataNode& addrSource = inPrimitive.nthInput(1).getProducer().getNode();
|
|
|
|
|
|
|
|
int32 offset = addrSource.nthInputConstant(1).i;
|
|
|
|
if ((offset >= -4096) && (offset <= 4095))
|
|
|
|
{
|
|
|
|
storeInsn = new(mPool) SparcStore(&inPrimitive, mPool, siSt, saRIR, offset);
|
|
|
|
useProducer(addrSource.nthInputVariable(0), *storeInsn, 1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
assert(false);
|
|
|
|
}
|
|
|
|
useProducer(inPrimitive.nthInputVariable(0), *storeInsn, 0); // <- store
|
|
|
|
useTemporaryVR(*storeInsn, constVr, 2); // <- value
|
|
|
|
defineProducer(inPrimitive, *storeInsn, 0); // -> store
|
|
|
|
}
|
|
|
|
|
|
|
|
void SparcSunOSEmitter::
|
|
|
|
emit_St_IRegisterIndirect(Primitive& inPrimitive)
|
|
|
|
{
|
|
|
|
DataNode& addrSource = inPrimitive.nthInput(1).getProducer().getNode();
|
|
|
|
|
|
|
|
int32 offset = addrSource.nthInputConstant(1).i;
|
|
|
|
if ((offset >= -4096) && (offset <= 4095))
|
|
|
|
{
|
|
|
|
SparcStore& storeInsn = *new(mPool) SparcStore(&inPrimitive, mPool, siSt, saRIR, offset);
|
|
|
|
useProducer(inPrimitive.nthInputVariable(0), storeInsn, 0); // <- store
|
|
|
|
useProducer(addrSource.nthInputVariable(0), storeInsn, 1); // <- address base
|
|
|
|
useProducer(inPrimitive.nthInputVariable(2), storeInsn, 2); // <- value
|
|
|
|
defineProducer(inPrimitive, storeInsn, 0); // -> store
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
assert(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VirtualRegister& SparcSunOSEmitter::
|
|
|
|
genLoadConstant(DataNode& inPrimitive, int32 constI)
|
|
|
|
{
|
|
|
|
if ((constI >= -4096) && (constI <= 4095))
|
|
|
|
{
|
|
|
|
SparcInsn& newInsn = *new(mPool) SparcInsn(&inPrimitive, mPool, siOr, constI ? saZIR : saZZR, constI & 0x1fff);
|
|
|
|
VirtualRegister& constantVr = defineTemporary(newInsn, 0);
|
|
|
|
return constantVr;
|
|
|
|
}
|
|
|
|
else if ((constI & 0x1fff) == 0)
|
|
|
|
{
|
|
|
|
// FIXME
|
|
|
|
assert(0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// FIXME
|
|
|
|
assert(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32 SparcSunOSEmitter::
|
|
|
|
getPrologSize() const
|
|
|
|
{
|
|
|
|
return 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SparcSunOSEmitter::
|
|
|
|
formatPrologToMemory(void* inWhere)
|
|
|
|
{
|
|
|
|
*(uint32*) inWhere = 0x9de3bf90; // save %sp,-112,%sp
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32 SparcSunOSEmitter::
|
|
|
|
getEpilogSize() const
|
|
|
|
{
|
|
|
|
return 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SparcSunOSEmitter::
|
|
|
|
formatEpilogToMemory(void* inWhere)
|
|
|
|
{
|
|
|
|
((uint32*) inWhere)[0] = 0x81c7e008; // ret
|
|
|
|
((uint32*) inWhere)[1] = 0x81e80000; // restore %g0,%g0,%g0
|
|
|
|
}
|