788 lines
18 KiB
C++
788 lines
18 KiB
C++
|
//----------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Assembe Alpha machine implementation.
|
|||
|
//
|
|||
|
// Copyright (C) Microsoft Corporation, 2000.
|
|||
|
//
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
|
|||
|
#include "ntsdp.hpp"
|
|||
|
|
|||
|
#include "alpha_dis.h"
|
|||
|
#include "alpha_optable.h"
|
|||
|
#include "alpha_strings.h"
|
|||
|
|
|||
|
#define OPSIZE 16
|
|||
|
|
|||
|
BOOL TestCharacter (PSTR inString, PSTR *outString, CHAR ch);
|
|||
|
ULONG GetIntReg(PSTR, PSTR *);
|
|||
|
ULONG GetFltReg(PSTR, PSTR *);
|
|||
|
|
|||
|
LONG
|
|||
|
GetValue (
|
|||
|
PSTR inString,
|
|||
|
PSTR *outString,
|
|||
|
BOOL fSigned,
|
|||
|
ULONG bitsize
|
|||
|
);
|
|||
|
|
|||
|
PSTR SkipWhite(PSTR *);
|
|||
|
ULONG GetToken(PSTR, PSTR *, PSTR, ULONG);
|
|||
|
|
|||
|
|
|||
|
ULONG ParseIntMemory(PSTR, PSTR *, POPTBLENTRY, PULONG64);
|
|||
|
ULONG ParseFltMemory(PSTR, PSTR *, POPTBLENTRY, PULONG64);
|
|||
|
ULONG ParseMemSpec(PSTR, PSTR *, POPTBLENTRY, PULONG64);
|
|||
|
ULONG ParseJump(PSTR, PSTR *, POPTBLENTRY, PULONG64);
|
|||
|
ULONG ParseIntBranch(PSTR, PSTR *, POPTBLENTRY, PULONG64);
|
|||
|
ULONG ParseFltBranch(PSTR, PSTR *, POPTBLENTRY, PULONG64);
|
|||
|
ULONG ParseIntOp(PSTR, PSTR *, POPTBLENTRY, PULONG64);
|
|||
|
ULONG ParsePal(PSTR, PSTR *, POPTBLENTRY, PULONG64);
|
|||
|
ULONG ParseUnknown(PSTR, PSTR *, POPTBLENTRY, PULONG64);
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*** assem - assemble instruction
|
|||
|
*
|
|||
|
* Purpose:
|
|||
|
* To assemble the instruction pointed by *poffset.
|
|||
|
*
|
|||
|
* Input:
|
|||
|
* pchInput - pointer to string to assemble
|
|||
|
*
|
|||
|
* Output:
|
|||
|
* *poffset - pointer to ADDR at which to assemble
|
|||
|
*
|
|||
|
* Exceptions:
|
|||
|
* error exit:
|
|||
|
* BADOPCODE - unknown or bad opcode
|
|||
|
* OPERAND - bad operand
|
|||
|
* ALIGNMENT - bad byte alignment in operand
|
|||
|
* DISPLACEMENT - overflow in displacement computation
|
|||
|
* BADREG - bad register name
|
|||
|
* EXTRACHARS - extra characters after legal instruction
|
|||
|
* MEMORY - write failure on assembled instruction
|
|||
|
*
|
|||
|
* Notes:
|
|||
|
* errors are handled by the calling program by outputting
|
|||
|
* the error string and reprompting the user for the same
|
|||
|
* instruction.
|
|||
|
*
|
|||
|
*************************************************************************/
|
|||
|
|
|||
|
void
|
|||
|
AlphaMachineInfo::Assemble (PADDR poffset, PSTR pchInput)
|
|||
|
{
|
|||
|
CHAR szOpcode[OPSIZE];
|
|||
|
ULONG instruction;
|
|||
|
|
|||
|
POPTBLENTRY pEntry;
|
|||
|
|
|||
|
//
|
|||
|
// Using the mnemonic token, find the entry in the assembler's
|
|||
|
// table for the associated instruction.
|
|||
|
//
|
|||
|
|
|||
|
if (GetToken(pchInput, &pchInput, szOpcode, OPSIZE) == 0)
|
|||
|
error(BADOPCODE);
|
|||
|
|
|||
|
|
|||
|
if ((pEntry = findStringEntry(szOpcode)) == (POPTBLENTRY) -1)
|
|||
|
error(BADOPCODE);
|
|||
|
|
|||
|
if (pEntry->eType == INVALID_ETYPE) {
|
|||
|
error(BADOPCODE);
|
|||
|
}
|
|||
|
//
|
|||
|
// Use the instruction format specific parser to encode the
|
|||
|
// instruction plus its operands.
|
|||
|
//
|
|||
|
|
|||
|
instruction = (*pEntry->parsFunc)
|
|||
|
(pchInput, &pchInput, pEntry, &(Flat(*poffset)));
|
|||
|
|
|||
|
//
|
|||
|
// Store the instruction into the target memory location and
|
|||
|
// increment the instruction pointer.
|
|||
|
//
|
|||
|
|
|||
|
if (SetMemString(poffset, &instruction, 4) != 4) {
|
|||
|
error(MEMORY);
|
|||
|
}
|
|||
|
|
|||
|
Flat(*poffset) += sizeof(ULONG);
|
|||
|
Off(*poffset) += sizeof(ULONG);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
TestCharacter (PSTR inString, PSTR *outString, CHAR ch)
|
|||
|
{
|
|||
|
|
|||
|
inString = SkipWhite(&inString);
|
|||
|
if (ch == *inString) {
|
|||
|
*outString = inString+1;
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
else {
|
|||
|
*outString = inString;
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*** GetIntReg - get integer register number
|
|||
|
*** GetFltReg - get floating register number
|
|||
|
*
|
|||
|
* Purpose:
|
|||
|
* From reading the input stream, return the register number.
|
|||
|
*
|
|||
|
* Input:
|
|||
|
* inString - pointer to input string
|
|||
|
*
|
|||
|
* Output:
|
|||
|
* *outString - pointer to character after register token in input stream
|
|||
|
*
|
|||
|
* Returns:
|
|||
|
* register number
|
|||
|
*
|
|||
|
* Exceptions:
|
|||
|
* error(BADREG) - bad register name
|
|||
|
*
|
|||
|
*************************************************************************/
|
|||
|
|
|||
|
PCHAR regNums[] = {
|
|||
|
"$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
|
|||
|
"$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
|
|||
|
"$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
|
|||
|
"$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
|
|||
|
};
|
|||
|
|
|||
|
PCHAR intRegNames[] = {
|
|||
|
g_R0, g_R1, g_R2, g_R3, g_R4, g_R5, g_R6, g_R7,
|
|||
|
g_R8, g_R9, g_R10, g_R11, g_R12, g_R13, g_R14, g_R15,
|
|||
|
g_R16, g_R17, g_R18, g_R19, g_R20, g_R21, g_R22, g_R23,
|
|||
|
g_R24, g_R25, g_R26, g_R27, g_R28, g_R29, g_R30, g_R31
|
|||
|
};
|
|||
|
|
|||
|
PCHAR fltRegNames[] = {
|
|||
|
g_F0, g_F1, g_F2, g_F3, g_F4, g_F5, g_F6, g_F7,
|
|||
|
g_F8, g_F9, g_F10, g_F11, g_F12, g_F13, g_F14, g_F15,
|
|||
|
g_F16, g_F17, g_F18, g_F19, g_F20, g_F21, g_F22, g_F23,
|
|||
|
g_F24, g_F25, g_F26, g_F27, g_F28, g_F29, g_F30, g_F31
|
|||
|
};
|
|||
|
|
|||
|
ULONG
|
|||
|
GetIntReg (PSTR inString, PSTR *outString)
|
|||
|
{
|
|||
|
CHAR szRegOp[5];
|
|||
|
ULONG index;
|
|||
|
|
|||
|
if (!GetToken(inString, outString, szRegOp, sizeof(szRegOp)))
|
|||
|
error(BADREG);
|
|||
|
|
|||
|
if (szRegOp[0] == '$') {
|
|||
|
//
|
|||
|
// use numbers
|
|||
|
//
|
|||
|
for (index = 0; index < 32; index++) {
|
|||
|
if (!strcmp(szRegOp, regNums[index]))
|
|||
|
return index;
|
|||
|
}
|
|||
|
} else {
|
|||
|
//
|
|||
|
// use names
|
|||
|
//
|
|||
|
for (index = 0; index < 32; index++) {
|
|||
|
if (!strcmp(szRegOp, intRegNames[index]))
|
|||
|
return index;
|
|||
|
}
|
|||
|
}
|
|||
|
error(BADREG);
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
ULONG
|
|||
|
GetFltReg (PSTR inString, PSTR *outString)
|
|||
|
{
|
|||
|
CHAR szRegOp[5];
|
|||
|
ULONG index;
|
|||
|
|
|||
|
if (!GetToken(inString, outString, szRegOp, sizeof(szRegOp)))
|
|||
|
error(BADREG);
|
|||
|
|
|||
|
if (szRegOp[0] == '$') {
|
|||
|
//
|
|||
|
// use numbers
|
|||
|
//
|
|||
|
for (index = 0; index < 32; index++) {
|
|||
|
if (!strcmp(szRegOp, regNums[index]))
|
|||
|
return index;
|
|||
|
}
|
|||
|
} else {
|
|||
|
//
|
|||
|
// use names
|
|||
|
//
|
|||
|
for (index = 0; index < 32; index++) {
|
|||
|
if (!strcmp(szRegOp, fltRegNames[index]))
|
|||
|
return index;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
error(BADREG);
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*** GetValue - get value from command line
|
|||
|
*
|
|||
|
* Purpose:
|
|||
|
* Use GetExpression to evaluate the next expression in the input
|
|||
|
* stream.
|
|||
|
*
|
|||
|
* Input:
|
|||
|
* inString - pointer to input stream
|
|||
|
* fSigned - TRUE if signed value
|
|||
|
* FALSE if unsigned value
|
|||
|
* bitsize - size of value allowed
|
|||
|
*
|
|||
|
* Output:
|
|||
|
* outString - character after the last character of the expression
|
|||
|
*
|
|||
|
* Returns:
|
|||
|
* value computed from input stream
|
|||
|
*
|
|||
|
* Exceptions:
|
|||
|
* error exit: OVERFLOW - value too large for bitsize
|
|||
|
*
|
|||
|
*************************************************************************/
|
|||
|
|
|||
|
LONG
|
|||
|
GetValue (
|
|||
|
PSTR inString,
|
|||
|
PSTR *outString,
|
|||
|
BOOL fSigned,
|
|||
|
ULONG bitsize
|
|||
|
)
|
|||
|
{
|
|||
|
ULONGLONG value;
|
|||
|
|
|||
|
inString = SkipWhite(&inString);
|
|||
|
g_CurCmd = inString;
|
|||
|
value = GetExpression();
|
|||
|
*outString = g_CurCmd;
|
|||
|
|
|||
|
if ((value > (ULONG)(1L << bitsize) - 1) &&
|
|||
|
(!fSigned || (value < (ULONG)(-1L << (bitsize - 1))))) {
|
|||
|
error(OVERFLOW);
|
|||
|
}
|
|||
|
|
|||
|
return (LONG)value;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*** SkipWhite - skip white-space
|
|||
|
*
|
|||
|
* Purpose:
|
|||
|
* To advance g_CurCmd over any spaces or tabs.
|
|||
|
*
|
|||
|
* Input:
|
|||
|
* *g_CurCmd - present command line position
|
|||
|
*
|
|||
|
*************************************************************************/
|
|||
|
|
|||
|
PSTR
|
|||
|
SkipWhite (PSTR * string)
|
|||
|
{
|
|||
|
while (**string == ' ' || **string == '\t')
|
|||
|
(*string)++;
|
|||
|
|
|||
|
return(*string);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*** GetToken - get token from command line
|
|||
|
*
|
|||
|
* Purpose:
|
|||
|
* Build a lower-case mapped token of maximum size maxcnt
|
|||
|
* at the string pointed by *psz. Token consist of the
|
|||
|
* set of characters a-z, A-Z, 0-9, $, and underscore.
|
|||
|
*
|
|||
|
* Input:
|
|||
|
* *inString - present command line position
|
|||
|
* maxcnt - maximum size of token allowed
|
|||
|
*
|
|||
|
* Output:
|
|||
|
* *outToken - token in lower case
|
|||
|
* *outString - pointer to first character beyond token in input
|
|||
|
*
|
|||
|
* Returns:
|
|||
|
* size of token if under maximum else 0
|
|||
|
*
|
|||
|
* Notes:
|
|||
|
* if string exceeds maximum size, the extra characters
|
|||
|
* are still processed, but ignored.
|
|||
|
*
|
|||
|
*************************************************************************/
|
|||
|
|
|||
|
ULONG
|
|||
|
GetToken (PSTR inString, PSTR *outString, PSTR outToken, ULONG maxcnt)
|
|||
|
{
|
|||
|
CHAR ch;
|
|||
|
ULONG count = 0;
|
|||
|
|
|||
|
inString = SkipWhite(&inString);
|
|||
|
|
|||
|
while (count < maxcnt) {
|
|||
|
ch = (CHAR)tolower(*inString);
|
|||
|
|
|||
|
if (!((ch >= '0' && ch <= '9') ||
|
|||
|
(ch >= 'a' && ch <= 'z') ||
|
|||
|
(ch == '$') ||
|
|||
|
(ch == '_') ||
|
|||
|
(ch == '#')))
|
|||
|
break;
|
|||
|
|
|||
|
count++;
|
|||
|
*outToken++ = ch;
|
|||
|
inString++;
|
|||
|
}
|
|||
|
|
|||
|
*outToken = '\0';
|
|||
|
*outString = inString;
|
|||
|
|
|||
|
return (count >= maxcnt ? 0 : count);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*** ParseIntMemory - parse integer memory instruction
|
|||
|
*
|
|||
|
* Purpose:
|
|||
|
* Given the users input, create the memory instruction.
|
|||
|
*
|
|||
|
* Input:
|
|||
|
* *inString - present input position
|
|||
|
* pEntry - pointer into the asmTable for this instr type
|
|||
|
*
|
|||
|
* Output:
|
|||
|
* *outstring - update input position
|
|||
|
*
|
|||
|
* Returns:
|
|||
|
* the instruction.
|
|||
|
*
|
|||
|
* Format:
|
|||
|
* op Ra, disp(Rb)
|
|||
|
*
|
|||
|
*************************************************************************/
|
|||
|
|
|||
|
ULONG
|
|||
|
ParseIntMemory(
|
|||
|
PSTR inString,
|
|||
|
PSTR *outString,
|
|||
|
POPTBLENTRY pEntry,
|
|||
|
PULONG64 poffset
|
|||
|
)
|
|||
|
{
|
|||
|
ULONG instruction;
|
|||
|
ULONG Ra;
|
|||
|
ULONG Rb;
|
|||
|
ULONG disp;
|
|||
|
|
|||
|
Ra = GetIntReg(inString, &inString);
|
|||
|
|
|||
|
if (!TestCharacter(inString, &inString, ','))
|
|||
|
error(OPERAND);
|
|||
|
|
|||
|
disp = GetValue(inString, &inString, TRUE, WIDTH_MEM_DISP);
|
|||
|
|
|||
|
if (!TestCharacter(inString, &inString, '('))
|
|||
|
error(OPERAND);
|
|||
|
|
|||
|
Rb = GetIntReg(inString, &inString);
|
|||
|
|
|||
|
if (!TestCharacter(inString, &inString, ')'))
|
|||
|
error(OPERAND);
|
|||
|
|
|||
|
if (!TestCharacter(inString, &inString, '\0'))
|
|||
|
error(EXTRACHARS);
|
|||
|
|
|||
|
instruction = OPCODE(pEntry->opCode) +
|
|||
|
REG_A(Ra) +
|
|||
|
REG_B(Rb) +
|
|||
|
MEM_DISP(disp);
|
|||
|
|
|||
|
return(instruction);
|
|||
|
}
|
|||
|
|
|||
|
/*** ParseFltMemory - parse floating point memory instruction
|
|||
|
*
|
|||
|
* Purpose:
|
|||
|
* Given the users input, create the memory instruction.
|
|||
|
*
|
|||
|
* Input:
|
|||
|
* *inString - present input position
|
|||
|
* pEntry - pointer into the asmTable for this instr type
|
|||
|
*
|
|||
|
* Output:
|
|||
|
* *outstring - update input position
|
|||
|
*
|
|||
|
* Returns:
|
|||
|
* the instruction.
|
|||
|
*
|
|||
|
* Format:
|
|||
|
* op Fa, disp(Rb)
|
|||
|
*
|
|||
|
*************************************************************************/
|
|||
|
|
|||
|
ULONG
|
|||
|
ParseFltMemory(PSTR inString,
|
|||
|
PSTR *outString,
|
|||
|
POPTBLENTRY pEntry,
|
|||
|
PULONG64 poffset)
|
|||
|
{
|
|||
|
ULONG instruction;
|
|||
|
ULONG Fa;
|
|||
|
ULONG Rb;
|
|||
|
ULONG disp;
|
|||
|
|
|||
|
Fa = GetFltReg(inString, &inString);
|
|||
|
|
|||
|
if (!TestCharacter(inString, &inString, ','))
|
|||
|
error(OPERAND);
|
|||
|
|
|||
|
disp = (ULONG)GetValue(inString, &inString, TRUE, WIDTH_MEM_DISP);
|
|||
|
|
|||
|
if (!TestCharacter(inString, &inString, '('))
|
|||
|
error(OPERAND);
|
|||
|
|
|||
|
Rb = GetIntReg(inString, &inString);
|
|||
|
|
|||
|
if (!TestCharacter(inString, &inString, ')'))
|
|||
|
error(OPERAND);
|
|||
|
|
|||
|
if (!TestCharacter(inString, &inString, '\0'))
|
|||
|
error(EXTRACHARS);
|
|||
|
|
|||
|
instruction = OPCODE(pEntry->opCode) +
|
|||
|
REG_A(Fa) +
|
|||
|
REG_B(Rb) +
|
|||
|
MEM_DISP(disp);
|
|||
|
|
|||
|
return(instruction);
|
|||
|
}
|
|||
|
|
|||
|
/*** ParseMemSpec - parse special memory instruction
|
|||
|
*
|
|||
|
* Purpose:
|
|||
|
* Given the users input, create the memory instruction.
|
|||
|
*
|
|||
|
* Input:
|
|||
|
* *inString - present input position
|
|||
|
* pEntry - pointer into the asmTable for this instr type
|
|||
|
*
|
|||
|
* Output:
|
|||
|
* *outstring - update input position
|
|||
|
*
|
|||
|
* Returns:
|
|||
|
* the instruction.
|
|||
|
*
|
|||
|
* Format:
|
|||
|
* op
|
|||
|
*
|
|||
|
*************************************************************************/
|
|||
|
ULONG ParseMemSpec(PSTR inString,
|
|||
|
PSTR *outString,
|
|||
|
POPTBLENTRY pEntry,
|
|||
|
PULONG64 poffset)
|
|||
|
{
|
|||
|
return(OPCODE(pEntry->opCode) +
|
|||
|
MEM_FUNC(pEntry->funcCode));
|
|||
|
}
|
|||
|
|
|||
|
/*** ParseJump - parse jump instruction
|
|||
|
*
|
|||
|
* Purpose:
|
|||
|
* Given the users input, create the memory instruction.
|
|||
|
*
|
|||
|
* Input:
|
|||
|
* *inString - present input position
|
|||
|
* pEntry - pointer into the asmTable for this instr type
|
|||
|
*
|
|||
|
* Output:
|
|||
|
* *outstring - update input position
|
|||
|
*
|
|||
|
* Returns:
|
|||
|
* the instruction.
|
|||
|
*
|
|||
|
* Format:
|
|||
|
* op Ra,(Rb),hint
|
|||
|
* op Ra,(Rb) - not really - we just support it in ntsd
|
|||
|
*
|
|||
|
*************************************************************************/
|
|||
|
|
|||
|
ULONG ParseJump(PSTR inString,
|
|||
|
PSTR *outString,
|
|||
|
POPTBLENTRY pEntry,
|
|||
|
PULONG64 poffset)
|
|||
|
{
|
|||
|
ULONG instruction;
|
|||
|
ULONG Ra;
|
|||
|
ULONG Rb;
|
|||
|
ULONG hint;
|
|||
|
|
|||
|
Ra = GetIntReg(inString, &inString);
|
|||
|
|
|||
|
if (!TestCharacter(inString, &inString, ','))
|
|||
|
error(OPERAND);
|
|||
|
|
|||
|
if (!TestCharacter(inString, &inString, '('))
|
|||
|
error(OPERAND);
|
|||
|
|
|||
|
Rb = GetIntReg(inString, &inString);
|
|||
|
|
|||
|
if (!TestCharacter(inString, &inString, ')'))
|
|||
|
error(OPERAND);
|
|||
|
|
|||
|
if (TestCharacter(inString, &inString, ',')) {
|
|||
|
//
|
|||
|
// User is giving us a hint
|
|||
|
//
|
|||
|
hint = GetValue(inString, &inString, TRUE, WIDTH_HINT);
|
|||
|
} else {
|
|||
|
hint = 0;
|
|||
|
}
|
|||
|
|
|||
|
if (!TestCharacter(inString, &inString, '\0'))
|
|||
|
error(EXTRACHARS);
|
|||
|
|
|||
|
instruction = OPCODE(pEntry->opCode) +
|
|||
|
JMP_FNC(pEntry->funcCode) +
|
|||
|
REG_A(Ra) +
|
|||
|
REG_B(Rb) +
|
|||
|
HINT(hint);
|
|||
|
|
|||
|
return(instruction);
|
|||
|
}
|
|||
|
|
|||
|
/*** ParseIntBranch - parse integer branch instruction
|
|||
|
*
|
|||
|
* Purpose:
|
|||
|
* Given the users input, create the memory instruction.
|
|||
|
*
|
|||
|
* Input:
|
|||
|
* *inString - present input position
|
|||
|
* pEntry - pointer into the asmTable for this instr type
|
|||
|
*
|
|||
|
* Output:
|
|||
|
* *outstring - update input position
|
|||
|
*
|
|||
|
* Returns:
|
|||
|
* the instruction.
|
|||
|
*
|
|||
|
* Format:
|
|||
|
* op Ra,disp
|
|||
|
*
|
|||
|
*************************************************************************/
|
|||
|
|
|||
|
ULONG ParseIntBranch(PSTR inString,
|
|||
|
PSTR *outString,
|
|||
|
POPTBLENTRY pEntry,
|
|||
|
PULONG64 poffset)
|
|||
|
{
|
|||
|
ULONG instruction;
|
|||
|
ULONG Ra;
|
|||
|
LONG disp;
|
|||
|
|
|||
|
Ra = GetIntReg(inString, &inString);
|
|||
|
|
|||
|
if (!TestCharacter(inString, &inString, ','))
|
|||
|
error(OPERAND);
|
|||
|
|
|||
|
//
|
|||
|
// the user gives an absolute address; we convert
|
|||
|
// that to a displacement, which is computed as a
|
|||
|
// difference off of (pc+1)
|
|||
|
// GetValue handles both numerics and symbolics
|
|||
|
//
|
|||
|
disp = GetValue(inString, &inString, TRUE, 32);
|
|||
|
|
|||
|
// get the relative displacement from the updated pc
|
|||
|
disp = disp - (LONG)((*poffset)+4);
|
|||
|
|
|||
|
// divide by four
|
|||
|
disp = disp >> 2;
|
|||
|
|
|||
|
if (!TestCharacter(inString, &inString, '\0'))
|
|||
|
error(EXTRACHARS);
|
|||
|
|
|||
|
instruction = OPCODE(pEntry->opCode) +
|
|||
|
REG_A(Ra) +
|
|||
|
BR_DISP(disp);
|
|||
|
|
|||
|
return(instruction);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*** ParseFltBranch - parse floating point branch instruction
|
|||
|
*
|
|||
|
* Purpose:
|
|||
|
* Given the users input, create the memory instruction.
|
|||
|
*
|
|||
|
* Input:
|
|||
|
* *inString - present input position
|
|||
|
* pEntry - pointer into the asmTable for this instr type
|
|||
|
*
|
|||
|
* Output:
|
|||
|
* *outstring - update input position
|
|||
|
*
|
|||
|
* Returns:
|
|||
|
* the instruction.
|
|||
|
*
|
|||
|
* Format:
|
|||
|
* op Fa,disp
|
|||
|
*
|
|||
|
*************************************************************************/
|
|||
|
ULONG ParseFltBranch(PSTR inString,
|
|||
|
PSTR *outString,
|
|||
|
POPTBLENTRY pEntry,
|
|||
|
PULONG64 poffset)
|
|||
|
{
|
|||
|
ULONG instruction;
|
|||
|
ULONG Ra;
|
|||
|
LONG disp;
|
|||
|
|
|||
|
Ra = GetFltReg(inString, &inString);
|
|||
|
|
|||
|
if (!TestCharacter(inString, &inString, ','))
|
|||
|
error(OPERAND);
|
|||
|
|
|||
|
//
|
|||
|
// the user gives an absolute address; we convert
|
|||
|
// that to a displacement, which is computed as a
|
|||
|
// difference off of (pc+1)
|
|||
|
// GetValue handles both numerics and symbolics
|
|||
|
//
|
|||
|
disp = GetValue(inString, &inString, TRUE, 32);
|
|||
|
|
|||
|
// get the relative displacement from the updated pc
|
|||
|
disp = disp - (LONG)((*poffset)+4);
|
|||
|
|
|||
|
// divide by four
|
|||
|
disp = disp >> 2;
|
|||
|
|
|||
|
if (!TestCharacter(inString, &inString, '\0'))
|
|||
|
error(EXTRACHARS);
|
|||
|
|
|||
|
instruction = OPCODE(pEntry->opCode) +
|
|||
|
REG_A(Ra) +
|
|||
|
BR_DISP(disp);
|
|||
|
|
|||
|
return(instruction);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*** ParseIntOp - parse integer operation
|
|||
|
*
|
|||
|
* Purpose:
|
|||
|
* Given the users input, create the memory instruction.
|
|||
|
*
|
|||
|
* Input:
|
|||
|
* *inString - present input position
|
|||
|
* pEntry - pointer into the asmTable for this instr type
|
|||
|
*
|
|||
|
* Output:
|
|||
|
* *outstring - update input position
|
|||
|
*
|
|||
|
* Returns:
|
|||
|
* the instruction.
|
|||
|
*
|
|||
|
* Format:
|
|||
|
* op Ra, Rb, Rc
|
|||
|
* op Ra, #lit, Rc
|
|||
|
*
|
|||
|
*************************************************************************/
|
|||
|
|
|||
|
ULONG ParseIntOp(PSTR inString,
|
|||
|
PSTR *outString,
|
|||
|
POPTBLENTRY pEntry,
|
|||
|
PULONG64 poffset)
|
|||
|
{
|
|||
|
ULONG instruction;
|
|||
|
ULONG Ra, Rb, Rc;
|
|||
|
ULONG lit;
|
|||
|
ULONG Format; // Whether there is a literal or 3rd reg
|
|||
|
|
|||
|
instruction = OPCODE(pEntry->opCode) +
|
|||
|
OP_FNC(pEntry->funcCode);
|
|||
|
|
|||
|
if (pEntry->opCode != SEXT_OP) {
|
|||
|
Ra = GetIntReg(inString, &inString);
|
|||
|
if (!TestCharacter(inString, &inString, ','))
|
|||
|
error(OPERAND);
|
|||
|
|
|||
|
} else {
|
|||
|
Ra = 31;
|
|||
|
}
|
|||
|
|
|||
|
if (TestCharacter(inString, &inString, '#')) {
|
|||
|
|
|||
|
//
|
|||
|
// User is giving us a literal value
|
|||
|
|
|||
|
lit = GetValue(inString, &inString, TRUE, WIDTH_LIT);
|
|||
|
Format = RBV_LITERAL_FORMAT;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// using a third register value
|
|||
|
|
|||
|
Rb = GetIntReg(inString, &inString);
|
|||
|
Format = RBV_REGISTER_FORMAT;
|
|||
|
}
|
|||
|
|
|||
|
if (!TestCharacter(inString, &inString, ','))
|
|||
|
error(OPERAND);
|
|||
|
|
|||
|
Rc = GetIntReg(inString, &inString);
|
|||
|
|
|||
|
if (!TestCharacter(inString, &inString, '\0'))
|
|||
|
error(EXTRACHARS);
|
|||
|
|
|||
|
instruction = instruction +
|
|||
|
REG_A(Ra) +
|
|||
|
RBV_TYPE(Format) +
|
|||
|
REG_C(Rc);
|
|||
|
|
|||
|
if (Format == RBV_REGISTER_FORMAT) {
|
|||
|
instruction = instruction + REG_B(Rb);
|
|||
|
} else {
|
|||
|
instruction = instruction + LIT(lit);
|
|||
|
}
|
|||
|
|
|||
|
return(instruction);
|
|||
|
}
|
|||
|
|
|||
|
ULONG ParsePal(PSTR inString,
|
|||
|
PSTR *outString,
|
|||
|
POPTBLENTRY pEntry,
|
|||
|
PULONG64 poffset)
|
|||
|
{
|
|||
|
if (!TestCharacter(inString, &inString, '\0'))
|
|||
|
error(EXTRACHARS);
|
|||
|
|
|||
|
return(OPCODE(pEntry->opCode) +
|
|||
|
PAL_FNC(pEntry->funcCode));
|
|||
|
}
|
|||
|
|
|||
|
ULONG ParseUnknown(PSTR inString,
|
|||
|
PSTR *outString,
|
|||
|
POPTBLENTRY pEntry,
|
|||
|
PULONG64 poffset)
|
|||
|
{
|
|||
|
dprintf("Unable to assemble %s\n", inString);
|
|||
|
error(BADOPCODE);
|
|||
|
return(0);
|
|||
|
}
|