зеркало из https://github.com/mozilla/pjs.git
225 строки
7.1 KiB
C++
225 строки
7.1 KiB
C++
/* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla 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/MPL/
|
|
*
|
|
* 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 [Open Source Virtual Machine.]
|
|
*
|
|
* The Initial Developer of the Original Code is Adobe System Incorporated. Portions created
|
|
* by the Initial Developer are Copyright (C)[ 2004-2006 ] Adobe Systems Incorporated. All Rights
|
|
* Reserved.
|
|
*
|
|
* Contributor(s): Adobe AS3 Team
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of either the GNU
|
|
* General Public License Version 2 or later (the "GPL"), or the GNU Lesser General Public
|
|
* License Version 2.1 or later (the "LGPL"), in which case the provisions of the GPL or the
|
|
* LGPL are applicable instead of those above. If you wish to allow use of your version of this
|
|
* file only under the terms of either the GPL or the LGPL, and not to allow others to use your
|
|
* version of this file under the terms of the MPL, indicate your decision by deleting provisions
|
|
* above and replace them with the notice and other provisions required by the GPL or the
|
|
* LGPL. If you do not delete the provisions above, a recipient may use your version of this file
|
|
* under the terms of any one of the MPL, the GPL or the LGPL.
|
|
*
|
|
***** END LICENSE BLOCK ***** */
|
|
|
|
#ifndef __avmplus_ArmAssembler__
|
|
#define __avmplus_ArmAssembler__
|
|
|
|
|
|
namespace avmplus
|
|
{
|
|
class ArmAssembler
|
|
{
|
|
public:
|
|
/* ARM registers */
|
|
typedef enum
|
|
{
|
|
R0 = 0,
|
|
R1 = 1,
|
|
R2 = 2,
|
|
R3 = 3,
|
|
R4 = 4,
|
|
R5 = 5,
|
|
R6 = 6,
|
|
R7 = 7,
|
|
R8 = 8,
|
|
R9 = 9,
|
|
R10 = 10,
|
|
FP = 11,
|
|
IP = 12,
|
|
SP = 13,
|
|
LR = 14,
|
|
PC = 15,
|
|
|
|
// Pseudo-register for floating point
|
|
F0 = 0,
|
|
|
|
Unknown = -1
|
|
}
|
|
Register;
|
|
|
|
/* ARM registers */
|
|
typedef enum
|
|
{
|
|
R0_mask = (1<<0),
|
|
R1_mask = (1<<1),
|
|
R2_mask = (1<<2),
|
|
R3_mask = (1<<3),
|
|
R4_mask = (1<<4),
|
|
R5_mask = (1<<5),
|
|
R6_mask = (1<<6),
|
|
R7_mask = (1<<7),
|
|
R8_mask = (1<<8),
|
|
R9_mask = (1<<9),
|
|
R10_mask = (1<<10),
|
|
FP_mask = (1<<11),
|
|
IP_mask = (1<<12),
|
|
SP_mask = (1<<13),
|
|
LR_mask = (1<<14),
|
|
PC_mask = (1<<15)
|
|
}
|
|
RegisterMask;
|
|
|
|
/* ARM condition codes */
|
|
typedef enum
|
|
{
|
|
EQ = 0x0, // Equal
|
|
NE = 0x1, // Not Equal
|
|
CS = 0x2, // Carry Set (or HS)
|
|
CC = 0x3, // Carry Clear (or LO)
|
|
MI = 0x4, // MInus
|
|
PL = 0x5, // PLus
|
|
VS = 0x6, // oVerflow Set
|
|
VC = 0x7, // oVerflow Clear
|
|
HI = 0x8, // HIgher
|
|
LS = 0x9, // Lower or Same
|
|
GE = 0xA, // Greater or Equal
|
|
LT = 0xB, // Less Than
|
|
GT = 0xC, // Greater Than
|
|
LE = 0xD, // Less or Equal
|
|
AL = 0xE, // ALways
|
|
NV = 0xF // NeVer
|
|
}
|
|
ConditionCode;
|
|
|
|
/* --- Data Processing Instructions --- */
|
|
|
|
/* Values for operator "a" */
|
|
typedef enum
|
|
{
|
|
AND_op = 0x0, // Boolean And Rd = Rn AND Op2
|
|
EOR_op = 0x1, // Boolean Eor Rd = Rn EOR Op2
|
|
SUB_op = 0x2, // Subtract Rd = Rn - Op2
|
|
RSB_op = 0x3, // Reverse Subtract Rd = Op2 - Rn
|
|
ADD_op = 0x4, // Addition Rd = Rn + Op2
|
|
ADC_op = 0x5, // Add with Carry Rd = Rn + Op2 + C
|
|
SBC_op = 0x6, // Subtract with Carry Rd = Rn - Op2 - (1-C)
|
|
RSC_op = 0x7, // Reverse Subtract with Carry Rd - Op2 - Rn - (1-C)
|
|
TST_op = 0x8, // Test bit Rn AND Op2
|
|
TEQ_op = 0x9, // Test equality Rn EOR Op2
|
|
CMP_op = 0xA, // Compare Rn - Op2
|
|
CMN_op = 0xB, // Compare Negative Rn + Op2
|
|
ORR_op = 0xC, // Boolean Or Rd = Rn OR Op2
|
|
MOV_op = 0xD, // Move value Rd = Op2
|
|
BIC_op = 0xE, // Bit Clear Rd = Rn AND NOT Op2
|
|
MVN_op = 0xF // Move Not Rd = NOT Op2
|
|
}
|
|
Operator;
|
|
|
|
/* Values for operand "t" */
|
|
typedef enum
|
|
{
|
|
LSL_imm = 0, // LSL #c - Logical Shift Left
|
|
LSL_reg = 1, // LSL Rc - Logical Shift Left
|
|
LSR_imm = 2, // LSR #c - Logical Shift Right
|
|
LSR_reg = 3, // LSR Rc - Logical Shift Right
|
|
ASR_imm = 4, // ASR #c - Arithmetic Shift Right
|
|
ASR_reg = 5, // ASR Rc - Arithmetic Shift Right
|
|
ROR_imm = 6, // Rotate Right (c != 0)
|
|
RRX = 6, // Rotate Right one bit with extend (c == 0)
|
|
ROR_reg = 7 // Rotate Right
|
|
}
|
|
ShiftOperator;
|
|
|
|
typedef uint32 MDInstruction;
|
|
|
|
/* Instruction pointer */
|
|
MDInstruction *mip;
|
|
MDInstruction *mipStart;
|
|
|
|
int mInstructionCount; // number of machine instructions
|
|
#define incInstructionCount() mInstructionCount++
|
|
|
|
/* Current condition code */
|
|
ConditionCode conditionCode;
|
|
|
|
ArmAssembler();
|
|
|
|
void SET_CONDITION_CODE(ConditionCode conditionCode);
|
|
|
|
void IMM32(int value);
|
|
void MOV(Register dst, Register src);
|
|
void STMFD_bang(Register dst, int mask);
|
|
void SUB_imm8(Register dst, Register src, int imm8);
|
|
void RSB_imm8(Register dst, Register src, int imm8);
|
|
void B(int offset24);
|
|
void BL(int offset24);
|
|
void LDR(Register dst, int offset, Register base);
|
|
void BIC_imm8(Register dst, Register src, int imm8);
|
|
void MOV_imm8(Register dst, int imm8);
|
|
void MOV_imm16(Register dst, int imm16);
|
|
void CMP_imm8(Register src, int imm8);
|
|
void ADD(Register dst, Register src1, Register src2);
|
|
void SUB(Register dst, Register src1, Register src2);
|
|
void AND(Register dst, Register src1, Register src2);
|
|
void ORR(Register dst, Register src1, Register src2);
|
|
void EOR(Register dst, Register src1, Register src2);
|
|
void MUL(Register dst, Register src1, Register src2);
|
|
void CMP(Register Rn, Register Rm);
|
|
void LSL(Register dst, Register src, Register rShift);
|
|
void LSR(Register dst, Register src, Register rShift);
|
|
void ASR(Register dst, Register src, Register rShift);
|
|
void LSL_i(Register dst, Register src, int iShift);
|
|
void LSR_i(Register dst, Register src, int iShift);
|
|
void ASR_i(Register dst, Register src, int iShift);
|
|
void STR(Register src, int offset, Register base);
|
|
void ADD_imm8(Register dst, Register src, int imm8);
|
|
void ADD_imm8_hi(Register dst, Register src, int imm8);
|
|
void ADD_imm16(Register dst, Register src, int imm16);
|
|
void AND_imm8(Register dst, Register src, int imm8);
|
|
void ORR_imm8(Register dst, Register src, int imm8);
|
|
void EOR_imm8(Register dst, Register src, int imm8);
|
|
void LDMFD(Register src, int mask);
|
|
void LDMFD_bang(Register src, int mask);
|
|
|
|
// Cheeseball way of doing imm32.
|
|
void MOV_imm32(Register dst, int imm32);
|
|
|
|
void flushDataCache(void *start, int len);
|
|
|
|
// Set if verbose output desired
|
|
#ifdef AVMPLUS_VERBOSE
|
|
bool verboseFlag;
|
|
#endif
|
|
PrintWriter *console;
|
|
|
|
// Immediate pool
|
|
MDInstruction *immediatePool;
|
|
int immediatePoolCount;
|
|
const static int kImmediatePoolMax = 16;
|
|
|
|
static const char* const regNames[];
|
|
#define gpregNames regNames
|
|
static const char* const conditionCodes[];
|
|
};
|
|
}
|
|
|
|
#endif /* __avmplus_ArmAssembler__ */
|