dmose%mozilla.org 2ccab49e6d updating license boilerplate to xPL v1.1
git-svn-id: svn://10.0.0.236/trunk@52526 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-02 06:38:29 +00:00

255 lines
10 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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/
*
* 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.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
//
// x86StdCall.cpp - StdCall calling convention
//
#include "x86StdCall.h"
#include "x86Emitter.h"
// Utility function to push one function-call argument on the stack
void
pushCallArg(DataConsumer& argument, DataNode* usesNode, InstructionDefine*& orderingDependency, Pool& inPool, x86Emitter& inEmitter)
{
// Do the first argument specially because that sets up the chain of ordering dependencies
int numOrderingUses = orderingDependency ? 1 : 0;
// If pushing constant arguments, use the immediate form of the push instruction
if (argument.getVariable().getCategory() == pcConst) {
switch (argument.getKind()) {
// 32-bit constants
case vkInt:
case vkAddr:
case vkFloat:
{
Uint32 constant = PrimConst::cast(argument.getVariable()).value.i;
x86Instruction& pushInsn = *new(inPool) x86Instruction(usesNode, inPool, iaPushImm, constant, atImmediateOnly, numOrderingUses, 1);
// First arg is handled differently
if (orderingDependency) {
inEmitter.useTemporaryOrder(pushInsn, *orderingDependency, 0);
inEmitter.redefineTemporaryOrder(pushInsn, *orderingDependency, 0);
} else {
orderingDependency = &inEmitter.defineTemporaryOrder(pushInsn, 0);
}
}
break;
// 64-bit constants require two immediate-form push instructions
case vkDouble:
case vkLong:
{
Int64 constant = PrimConst::cast(argument.getVariable()).value.l;
Int32 low = (Int32)((Uint64)constant & 0xFFFFFFFF);
Int32 high = (Int32)((Uint64)constant >> 32);
x86Instruction& pushInsnHi = *new(inPool) x86Instruction(usesNode, inPool, iaPushImm, high, atImmediateOnly, numOrderingUses, 1);
// First arg is handled differently
if (orderingDependency) {
inEmitter.useTemporaryOrder(pushInsnHi, *orderingDependency, 0);
inEmitter.redefineTemporaryOrder(pushInsnHi, *orderingDependency, 0);
} else {
orderingDependency = &inEmitter.defineTemporaryOrder(pushInsnHi, 0);
}
x86Instruction& pushInsnLo = *new(inPool) x86Instruction(usesNode, inPool, iaPushImm, low, atImmediateOnly, 1, 1);
inEmitter.useTemporaryOrder(pushInsnLo, *orderingDependency, 0);
inEmitter.redefineTemporaryOrder(pushInsnLo, *orderingDependency, 0);
}
break;
default:
assert(0);
}
return;
}
// Push non-constant function call argument
switch (argument.getKind()) {
case vkInt:
case vkAddr:
{
x86Instruction& storeParam = *new(inPool) x86Instruction(usesNode, inPool, ePush, atRegDirect, 1 + numOrderingUses, 1);
inEmitter.useProducer(argument.getVariable(), storeParam, 0);
// First arg is handled differently
if (orderingDependency) {
inEmitter.useTemporaryOrder(storeParam, *orderingDependency, 1);
inEmitter.redefineTemporaryOrder(storeParam, *orderingDependency, 0);
} else {
orderingDependency = &inEmitter.defineTemporaryOrder(storeParam, 0);
}
}
break;
case vkFloat:
{
InsnDoubleOpDir& copyParamInsn = *new(inPool) InsnDoubleOpDir(usesNode, inPool, raCopyI, atRegAllocStackSlot, atRegDirect, 1, 1);
inEmitter.useProducer(argument.getVariable(), copyParamInsn, 0, vrcStackSlot);
VirtualRegister& vr = inEmitter.defineTemporary(copyParamInsn, 0);
x86Instruction& storeParamInsn = *new(inPool) x86Instruction(usesNode, inPool, ePush, atRegDirect, 1 + numOrderingUses, 1);
inEmitter.useTemporaryVR(storeParamInsn, vr, 0);
// First arg is handled differently
if (orderingDependency) {
inEmitter.useTemporaryOrder(storeParamInsn, *orderingDependency, 1);
inEmitter.redefineTemporaryOrder(storeParamInsn, *orderingDependency, 0);
} else {
orderingDependency = &inEmitter.defineTemporaryOrder(storeParamInsn, 0);
}
}
break;
case vkDouble:
{
// Push high 32-bits of double
InsnDoubleOpDir& copyParamInsnHi = *new(inPool) InsnDoubleOpDir(usesNode, inPool, raCopyI, atRegAllocStackSlotHi32, atRegDirect, 1, 2);
inEmitter.useProducer(argument.getVariable(), copyParamInsnHi, 0, vrcStackSlot);
VirtualRegister& vrHi = inEmitter.defineTemporary(copyParamInsnHi, 0);
x86Instruction& storeParamInsnHi = *new(inPool) x86Instruction(usesNode, inPool, ePush, atRegDirect, 1 + numOrderingUses, 1);
inEmitter.useTemporaryVR(storeParamInsnHi, vrHi, 0);
// First arg is handled differently
if (orderingDependency) {
inEmitter.useTemporaryOrder(storeParamInsnHi, *orderingDependency, 1);
inEmitter.redefineTemporaryOrder(storeParamInsnHi, *orderingDependency, 0);
} else {
orderingDependency = &inEmitter.defineTemporaryOrder(storeParamInsnHi, 0);
}
// Push low 32-bits of double
InsnDoubleOpDir& copyParamInsnLo = *new(inPool) InsnDoubleOpDir(usesNode, inPool, raCopyI, atRegAllocStackSlot, atRegDirect, 1, 2);
inEmitter.useProducer(argument.getVariable(), copyParamInsnLo, 0, vrcStackSlot);
VirtualRegister& vrLo = inEmitter.defineTemporary(copyParamInsnLo, 0);
x86Instruction& storeParamInsnLo = *new(inPool) x86Instruction(usesNode, inPool, ePush, atRegDirect, 2, 1);
inEmitter.useTemporaryVR(storeParamInsnLo, vrLo, 0);
inEmitter.useTemporaryOrder(storeParamInsnLo, *orderingDependency, 1);
inEmitter.redefineTemporaryOrder(storeParamInsnLo, *orderingDependency, 0);
}
break;
case vkLong:
{
x86Instruction& storeParamHigh = *new(inPool) x86Instruction(usesNode, inPool, ePush, atRegDirect, 1 + numOrderingUses, 1);
inEmitter.useProducer(argument.getVariable(), storeParamHigh, 0, vrcInteger, vidHigh);
// First arg is handled differently
if (orderingDependency) {
inEmitter.useTemporaryOrder(storeParamHigh, *orderingDependency, 1);
inEmitter.redefineTemporaryOrder(storeParamHigh, *orderingDependency, 0);
} else {
orderingDependency = &inEmitter.defineTemporaryOrder(storeParamHigh, 0);
}
x86Instruction& storeParamLow = *new(inPool) x86Instruction(usesNode, inPool, ePush, atRegDirect, 2, 1);
inEmitter.useProducer(argument.getVariable(), storeParamLow, 0, vrcInteger, vidLow);
inEmitter.useTemporaryOrder(storeParamLow, *orderingDependency, 1);
inEmitter.redefineTemporaryOrder(storeParamLow, *orderingDependency, 0);
}
break;
default:
assert(false);
}
}
void x86Emitter::
emitArguments(ControlNode::BeginExtra& inBeginNode)
{
if (inBeginNode.nArguments == 0)
return;
InsnExternalDefine& defineInsn = *new(mPool) InsnExternalDefine(&inBeginNode[0], mPool, inBeginNode.nArguments * 2);
// do appropriate loads for each argument
Uint32 curStackOffset = 8;
Uint8 curIndex = 0; // Index into defineInsn
unsigned int curArgument;
for (curArgument = 0; curArgument < inBeginNode.nArguments; curArgument++)
{
PrimArg& curArg = inBeginNode[curArgument];
switch (curArg.getOperation())
{
case poArg_I:
case poArg_A:
if (curArg.hasConsumers())
{
InsnDoubleOpDir& loadParam = *new(mPool) InsnDoubleOpDir(&curArg, mPool, raLoadI, curStackOffset, atStackOffset, atRegDirect, 1, 1);
useTemporaryOrder(loadParam, defineTemporaryOrder(defineInsn, curIndex), 0);
defineProducer(curArg, loadParam, 0);
}
curIndex++;
curStackOffset += 4;
break;
case poArg_F:
if (curArg.hasConsumers())
emit_ArgF(curArg, defineTemporaryOrder(defineInsn, curIndex), curStackOffset);
curIndex++;
curStackOffset += 4;
break;
case poArg_L:
if (curArg.hasConsumers())
{
InsnDoubleOpDir& loadHi = *new(mPool) InsnDoubleOpDir(&curArg, mPool, raLoadI, curStackOffset + 4, atStackOffset, atRegDirect, 1, 1);
InsnDoubleOpDir& loadLo = *new(mPool) InsnDoubleOpDir(&curArg, mPool, raLoadI, curStackOffset, atStackOffset, atRegDirect, 1, 1);
useTemporaryOrder(loadLo, defineTemporaryOrder(defineInsn, curIndex), 0);
useTemporaryOrder(loadHi, defineTemporaryOrder(defineInsn, curIndex + 1), 0);
defineProducer(curArg, loadLo, 0, vrcInteger, vidLow);
defineProducer(curArg, loadHi, 0, vrcInteger, vidHigh);
}
curIndex += 2;
curStackOffset += 8;
break;
case poArg_D:
if (curArg.hasConsumers())
emit_ArgD(curArg, defineTemporaryOrder(defineInsn, curIndex), curStackOffset);
curIndex++;
curStackOffset += 8;
break;
default:
assert(false);
}
}
// continue counting from before
// make all the rest of the defines as type none
for (;curIndex < inBeginNode.nArguments * 2; curIndex++)
{
defineInsn.getInstructionDefineBegin()[curIndex].kind = udNone;
}
}