302 lines
7.1 KiB
C++
302 lines
7.1 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):
|
|
*/
|
|
|
|
#include "Fundamentals.h"
|
|
#include "SparcInstruction.h"
|
|
#include "ControlNodes.h"
|
|
|
|
SparcInstructionInfo siInfo[nSparcInstructionKind] =
|
|
{
|
|
{ siAnd, 2, 0x01, "and" },
|
|
{ siAndCC, 2, 0x11, "andcc" },
|
|
{ siAndN, 2, 0x05, "andn" },
|
|
{ siAndNCC, 2, 0x15, "andncc" },
|
|
{ siOr, 2, 0x02, "or" },
|
|
{ siOrCC, 2, 0x12, "orcc" },
|
|
{ siOrN, 2, 0x06, "orn" },
|
|
{ siOrNCC, 2, 0x16, "orncc" },
|
|
{ siXor, 2, 0x03, "xor" },
|
|
{ siXorCC, 2, 0x13, "xorcc" },
|
|
{ siXNor, 2, 0x07, "xnor" },
|
|
{ siXNorCC, 2, 0x17, "xnorcc" },
|
|
{ siSll, 2, 0x25, "sll" },
|
|
{ siSrl, 2, 0x26, "srl" },
|
|
{ siSra, 2, 0x27, "sra" },
|
|
{ siAdd, 2, 0x00, "add" },
|
|
{ siAddCC, 2, 0x10, "addcc" },
|
|
{ siAddX, 2, 0x08, "addx" },
|
|
{ siAddXCC, 2, 0x18, "addxcc" },
|
|
{ siSub, 2, 0x04, "sub" },
|
|
{ siSubCC, 2, 0x14, "subcc" },
|
|
{ siSubX, 2, 0x0c, "subx" },
|
|
{ siSubXCC, 2, 0x1c, "subxcc" },
|
|
{ siUMul, 2, 0x0a, "umul" },
|
|
{ siUMulCC, 2, 0x1a, "umulcc" },
|
|
{ siSMul, 2, 0x0b, "smul" },
|
|
{ siSMulCC, 2, 0x1b, "smulcc" },
|
|
{ siUDiv, 2, 0x0e, "udiv" },
|
|
{ siUDivCC, 2, 0x1e, "udivcc" },
|
|
{ siSDiv, 2, 0x0f, "sdiv" },
|
|
{ siSDivCC, 2, 0x1f, "sdvicc" },
|
|
{ siTrap, 2, 0x3a, "trap" },
|
|
{ siLdSb, 3, 0x09, "ldsb" },
|
|
{ siLdSh, 3, 0x0a, "ldsh" },
|
|
{ siLdUb, 3, 0x01, "ldub" },
|
|
{ siLdUh, 3, 0x02, "lduh" },
|
|
{ siLd, 3, 0x00, "ld" },
|
|
{ siLdd, 3, 0x03, "ldd" },
|
|
{ siStSb, 3, 0x05, "stsb" },
|
|
{ siStSh, 3, 0x06, "stsh" },
|
|
{ siSt, 3, 0x04, "st" },
|
|
{ siStd, 3, 0x07, "std" },
|
|
{ siBranch, 0, 0x02, "b" },
|
|
};
|
|
|
|
SparcAccessInfo saInfo[nSparcAccessKind] =
|
|
{
|
|
{ saRRR, 2, 1 },
|
|
{ saRIR, 1, 1 },
|
|
{ saRZR, 1, 1 },
|
|
{ saZRR, 1, 1 },
|
|
{ saZIR, 0, 1 },
|
|
{ saZZR, 0, 1 },
|
|
{ saRRZ, 2, 0 },
|
|
{ saRIZ, 1, 0 },
|
|
{ saRZZ, 1, 0 },
|
|
};
|
|
|
|
SparcConditionInfo scInfo[nSparcConditionKind] =
|
|
{
|
|
{ scA, 0x08, "a" },
|
|
{ scN, 0x00, "n" },
|
|
{ scNe, 0x09, "ne" },
|
|
{ scE, 0x01, "e" },
|
|
{ scG, 0x0a, "g" },
|
|
{ scLe, 0x02, "le" },
|
|
{ scGe, 0x0b, "ge" },
|
|
{ scL, 0x03, "l" },
|
|
{ scGu, 0x0c, "gu" },
|
|
{ scLeu, 0x04, "leu" },
|
|
{ scCc, 0x0d, "cc" },
|
|
{ scGeu, 0x0d, "cc" },
|
|
{ scCs, 0x05, "cs" },
|
|
{ scLu, 0x05, "cs" },
|
|
{ scPos, 0x0e, "pos" },
|
|
{ scNeg, 0x06, "neg" },
|
|
{ scVc, 0x0f, "vc" },
|
|
{ scVs, 0x07, "vs" }
|
|
};
|
|
|
|
char* registerNumberToString[] =
|
|
{
|
|
"g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
|
|
"o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7",
|
|
"l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
|
|
"i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7"
|
|
};
|
|
|
|
uint8 registerNumberToColor[] =
|
|
{
|
|
255, 255, 255, 255, 255, 255, 255, 255,
|
|
8, 9, 10, 11, 12, 13, 255, 255,
|
|
0, 1, 2, 3, 4, 5, 6, 7,
|
|
14, 15, 16, 17, 18, 19, 255, 255
|
|
};
|
|
|
|
SparcRegisterNumber colorToRegisterNumber[] =
|
|
{
|
|
l0, l1, l2, l3, l4, l5, l6, l7,
|
|
o0, o1, o2, o3, o4, o5,
|
|
i0, i1, i2, i3, i4, i5,
|
|
};
|
|
|
|
void SparcFormatBCond::
|
|
formatToMemory(void* inStart, uint32 inOffset)
|
|
{
|
|
uint32 insn = 0;
|
|
insn |= (siInfo[kind].op & 0x3) << 30;
|
|
if (a) insn |= (1 << 29);
|
|
insn |= (scInfo[cond].cond & 0xf) << 25;
|
|
insn |= (siInfo[kind].op3 & 0x7) << 22;
|
|
insn |= ((target.getNativeOffset() - inOffset) >> 2) & 0x3fffff;
|
|
*(uint32*) inStart = insn;
|
|
if (a) ((uint32*) inStart)[1] = 1 << 24;
|
|
}
|
|
|
|
void SparcFormatC::
|
|
formatToMemory(void* inStart, uint32 /*inOffset*/)
|
|
{
|
|
uint32 insn = 0;
|
|
|
|
insn |= (siInfo[kind].op & 0x3) << 30;
|
|
insn |= (getRD() & 0x1f) << 25;
|
|
insn |= (siInfo[kind].op3 & 0x3f) << 19;
|
|
insn |= (getRS1() & 0x1f) << 14;
|
|
if (imm13)
|
|
insn |= (imm13 | 0x2000);
|
|
else
|
|
insn |= getRS2();
|
|
|
|
*(uint32*) inStart = insn;
|
|
}
|
|
|
|
|
|
void SparcFormatC::
|
|
printPretty(FILE* f)
|
|
{
|
|
switch (access)
|
|
{
|
|
case saRIR: case saZIR: case saRIZ:
|
|
fprintf(f, "%s %%%s,%d,%%%s", siInfo[kind].string,
|
|
registerNumberToString[getRS1()],
|
|
imm13,
|
|
registerNumberToString[getRD()]);
|
|
break;
|
|
default:
|
|
fprintf(f, "%s %%%s,%%%s,%%%s", siInfo[kind].string,
|
|
registerNumberToString[getRS1()],
|
|
registerNumberToString[getRS2()],
|
|
registerNumberToString[getRD()]);
|
|
}
|
|
}
|
|
|
|
void SparcLoadStore::
|
|
printPretty(FILE* f)
|
|
{
|
|
switch (access)
|
|
{
|
|
case saRIR: case saRZR:
|
|
if (isLoad)
|
|
fprintf(f, "%s [%%%s+%d],%%%s", siInfo[kind].string,
|
|
registerNumberToString[getRS1()],
|
|
imm13,
|
|
registerNumberToString[getRD()]);
|
|
else
|
|
fprintf(f, "%s %%%s,[%%%s+%d]", siInfo[kind].string,
|
|
registerNumberToString[getRD()],
|
|
registerNumberToString[getRS1()],
|
|
imm13);
|
|
break;
|
|
default:
|
|
if (isLoad)
|
|
fprintf(f, "%s [%%%s+%%%s],%%%s", siInfo[kind].string,
|
|
registerNumberToString[getRS1()],
|
|
registerNumberToString[getRS2()],
|
|
registerNumberToString[getRD()]);
|
|
else
|
|
fprintf(f, "%s %%%s,[%%%s+%%%s]", siInfo[kind].string,
|
|
registerNumberToString[getRD()],
|
|
registerNumberToString[getRS1()],
|
|
registerNumberToString[getRS2()]);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void SparcTrap::
|
|
printPretty(FILE* f)
|
|
{
|
|
fprintf(f, "t%s throw_exception", scInfo[cond].string);
|
|
}
|
|
|
|
void SparcFormatBCond::
|
|
printPretty(FILE* f)
|
|
{
|
|
fprintf(f, "%s%s%s N%d%s", siInfo[kind].string, scInfo[cond].string, a ? ",a" : "",
|
|
target.dfsNum, a ? "; nop" : "");
|
|
}
|
|
|
|
uint8 SparcFormatC::
|
|
getRS1()
|
|
{
|
|
switch (access)
|
|
{
|
|
case saZRR: case saZIR: case saZZR:
|
|
return g0;
|
|
|
|
default:
|
|
return useToRegisterNumber(getInstructionUseBegin()[0]);
|
|
}
|
|
}
|
|
|
|
uint8 SparcFormatC::
|
|
getRS2()
|
|
{
|
|
#if DEBUG
|
|
if (access == saRIR || access == saZIR || access == saRIZ) assert(0);
|
|
#endif
|
|
|
|
switch (access)
|
|
{
|
|
case saZZR: case saRZZ: case saRZR:
|
|
return g0;
|
|
|
|
default:
|
|
return useToRegisterNumber(getInstructionUseBegin()[1]);
|
|
}
|
|
}
|
|
|
|
uint8 SparcFormatC::
|
|
getRD()
|
|
{
|
|
switch (access)
|
|
{
|
|
case saRRZ: case saRIZ: case saRZZ:
|
|
return g0;
|
|
|
|
default:
|
|
return defineToRegisterNumber(getInstructionDefineBegin()[0]);
|
|
}
|
|
}
|
|
|
|
uint8 SparcLoadStore::
|
|
getRS1()
|
|
{
|
|
switch (access)
|
|
{
|
|
case saZRR: case saZIR: case saZZR:
|
|
return g0;
|
|
|
|
default:
|
|
return useToRegisterNumber(getInstructionUseBegin()[isLoadC ? 0 : 1]);
|
|
}
|
|
}
|
|
|
|
uint8 SparcLoadStore::
|
|
getRS2()
|
|
{
|
|
assert(0);
|
|
}
|
|
|
|
uint8 SparcLoadStore::
|
|
getRD()
|
|
{
|
|
switch (access)
|
|
{
|
|
case saRRZ: case saRIZ: case saRZZ:
|
|
return g0;
|
|
|
|
default:
|
|
return (isLoad) ? defineToRegisterNumber(getInstructionDefineBegin()[hasMemoryEdge ? 1 : 0]) :
|
|
useToRegisterNumber(getInstructionUseBegin()[2]);
|
|
}
|
|
}
|