Add MIPS support to pixelflinger.
See the comment-block at the top of MIPSAssembler.cpp for implementation overview. Change-Id: Id492c10610574af8c89c38d19e12fafc3652c28a
This commit is contained in:
parent
ae8927aa05
commit
2bc2b79278
|
@ -44,6 +44,8 @@ PIXELFLINGER_CFLAGS += -fstrict-aliasing -fomit-frame-pointer
|
|||
endif
|
||||
|
||||
ifeq ($(TARGET_ARCH),mips)
|
||||
PIXELFLINGER_SRC_FILES += codeflinger/MIPSAssembler.cpp
|
||||
PIXELFLINGER_SRC_FILES += codeflinger/mips_disassem.c
|
||||
PIXELFLINGER_SRC_FILES += arch-mips/t32cb16blend.S
|
||||
PIXELFLINGER_CFLAGS += -fstrict-aliasing -fomit-frame-pointer
|
||||
endif
|
||||
|
|
|
@ -76,6 +76,11 @@ void ARMAssembler::reset()
|
|||
mComments.clear();
|
||||
}
|
||||
|
||||
int ARMAssembler::getCodegenArch()
|
||||
{
|
||||
return CODEGEN_ARCH_ARM;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void ARMAssembler::disassemble(const char* name)
|
||||
|
@ -444,5 +449,146 @@ void ARMAssembler::UBFX(int cc, int Rd, int Rn, int lsb, int width)
|
|||
*mPC++ = (cc<<28) | 0x7E00000 | ((width-1)<<16) | (Rd<<12) | (lsb<<7) | 0x50 | Rn;
|
||||
}
|
||||
|
||||
#if 0
|
||||
#pragma mark -
|
||||
#pragma mark Addressing modes...
|
||||
#endif
|
||||
|
||||
int ARMAssembler::buildImmediate(
|
||||
uint32_t immediate, uint32_t& rot, uint32_t& imm)
|
||||
{
|
||||
rot = 0;
|
||||
imm = immediate;
|
||||
if (imm > 0x7F) { // skip the easy cases
|
||||
while (!(imm&3) || (imm&0xFC000000)) {
|
||||
uint32_t newval;
|
||||
newval = imm >> 2;
|
||||
newval |= (imm&3) << 30;
|
||||
imm = newval;
|
||||
rot += 2;
|
||||
if (rot == 32) {
|
||||
rot = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
rot = (16 - (rot>>1)) & 0xF;
|
||||
|
||||
if (imm>=0x100)
|
||||
return -EINVAL;
|
||||
|
||||
if (((imm>>(rot<<1)) | (imm<<(32-(rot<<1)))) != immediate)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// shifters...
|
||||
|
||||
bool ARMAssembler::isValidImmediate(uint32_t immediate)
|
||||
{
|
||||
uint32_t rot, imm;
|
||||
return buildImmediate(immediate, rot, imm) == 0;
|
||||
}
|
||||
|
||||
uint32_t ARMAssembler::imm(uint32_t immediate)
|
||||
{
|
||||
uint32_t rot, imm;
|
||||
int err = buildImmediate(immediate, rot, imm);
|
||||
|
||||
LOG_ALWAYS_FATAL_IF(err==-EINVAL,
|
||||
"immediate %08x cannot be encoded",
|
||||
immediate);
|
||||
|
||||
LOG_ALWAYS_FATAL_IF(err,
|
||||
"immediate (%08x) encoding bogus!",
|
||||
immediate);
|
||||
|
||||
return (1<<25) | (rot<<8) | imm;
|
||||
}
|
||||
|
||||
uint32_t ARMAssembler::reg_imm(int Rm, int type, uint32_t shift)
|
||||
{
|
||||
return ((shift&0x1F)<<7) | ((type&0x3)<<5) | (Rm&0xF);
|
||||
}
|
||||
|
||||
uint32_t ARMAssembler::reg_rrx(int Rm)
|
||||
{
|
||||
return (ROR<<5) | (Rm&0xF);
|
||||
}
|
||||
|
||||
uint32_t ARMAssembler::reg_reg(int Rm, int type, int Rs)
|
||||
{
|
||||
return ((Rs&0xF)<<8) | ((type&0x3)<<5) | (1<<4) | (Rm&0xF);
|
||||
}
|
||||
|
||||
// addressing modes...
|
||||
// LDR(B)/STR(B)/PLD (immediate and Rm can be negative, which indicate U=0)
|
||||
uint32_t ARMAssembler::immed12_pre(int32_t immed12, int W)
|
||||
{
|
||||
LOG_ALWAYS_FATAL_IF(abs(immed12) >= 0x800,
|
||||
"LDR(B)/STR(B)/PLD immediate too big (%08x)",
|
||||
immed12);
|
||||
return (1<<24) | (((uint32_t(immed12)>>31)^1)<<23) |
|
||||
((W&1)<<21) | (abs(immed12)&0x7FF);
|
||||
}
|
||||
|
||||
uint32_t ARMAssembler::immed12_post(int32_t immed12)
|
||||
{
|
||||
LOG_ALWAYS_FATAL_IF(abs(immed12) >= 0x800,
|
||||
"LDR(B)/STR(B)/PLD immediate too big (%08x)",
|
||||
immed12);
|
||||
|
||||
return (((uint32_t(immed12)>>31)^1)<<23) | (abs(immed12)&0x7FF);
|
||||
}
|
||||
|
||||
uint32_t ARMAssembler::reg_scale_pre(int Rm, int type,
|
||||
uint32_t shift, int W)
|
||||
{
|
||||
return (1<<25) | (1<<24) |
|
||||
(((uint32_t(Rm)>>31)^1)<<23) | ((W&1)<<21) |
|
||||
reg_imm(abs(Rm), type, shift);
|
||||
}
|
||||
|
||||
uint32_t ARMAssembler::reg_scale_post(int Rm, int type, uint32_t shift)
|
||||
{
|
||||
return (1<<25) | (((uint32_t(Rm)>>31)^1)<<23) | reg_imm(abs(Rm), type, shift);
|
||||
}
|
||||
|
||||
// LDRH/LDRSB/LDRSH/STRH (immediate and Rm can be negative, which indicate U=0)
|
||||
uint32_t ARMAssembler::immed8_pre(int32_t immed8, int W)
|
||||
{
|
||||
uint32_t offset = abs(immed8);
|
||||
|
||||
LOG_ALWAYS_FATAL_IF(abs(immed8) >= 0x100,
|
||||
"LDRH/LDRSB/LDRSH/STRH immediate too big (%08x)",
|
||||
immed8);
|
||||
|
||||
return (1<<24) | (1<<22) | (((uint32_t(immed8)>>31)^1)<<23) |
|
||||
((W&1)<<21) | (((offset&0xF0)<<4)|(offset&0xF));
|
||||
}
|
||||
|
||||
uint32_t ARMAssembler::immed8_post(int32_t immed8)
|
||||
{
|
||||
uint32_t offset = abs(immed8);
|
||||
|
||||
LOG_ALWAYS_FATAL_IF(abs(immed8) >= 0x100,
|
||||
"LDRH/LDRSB/LDRSH/STRH immediate too big (%08x)",
|
||||
immed8);
|
||||
|
||||
return (1<<22) | (((uint32_t(immed8)>>31)^1)<<23) |
|
||||
(((offset&0xF0)<<4) | (offset&0xF));
|
||||
}
|
||||
|
||||
uint32_t ARMAssembler::reg_pre(int Rm, int W)
|
||||
{
|
||||
return (1<<24) | (((uint32_t(Rm)>>31)^1)<<23) | ((W&1)<<21) | (abs(Rm)&0xF);
|
||||
}
|
||||
|
||||
uint32_t ARMAssembler::reg_post(int Rm)
|
||||
{
|
||||
return (((uint32_t(Rm)>>31)^1)<<23) | (abs(Rm)&0xF);
|
||||
}
|
||||
|
||||
}; // namespace android
|
||||
|
||||
|
|
|
@ -52,11 +52,42 @@ public:
|
|||
virtual void reset();
|
||||
|
||||
virtual int generate(const char* name);
|
||||
virtual int getCodegenArch();
|
||||
|
||||
virtual void prolog();
|
||||
virtual void epilog(uint32_t touched);
|
||||
virtual void comment(const char* string);
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// shifters and addressing modes
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
// shifters...
|
||||
virtual bool isValidImmediate(uint32_t immed);
|
||||
virtual int buildImmediate(uint32_t i, uint32_t& rot, uint32_t& imm);
|
||||
|
||||
virtual uint32_t imm(uint32_t immediate);
|
||||
virtual uint32_t reg_imm(int Rm, int type, uint32_t shift);
|
||||
virtual uint32_t reg_rrx(int Rm);
|
||||
virtual uint32_t reg_reg(int Rm, int type, int Rs);
|
||||
|
||||
// addressing modes...
|
||||
// LDR(B)/STR(B)/PLD
|
||||
// (immediate and Rm can be negative, which indicates U=0)
|
||||
virtual uint32_t immed12_pre(int32_t immed12, int W=0);
|
||||
virtual uint32_t immed12_post(int32_t immed12);
|
||||
virtual uint32_t reg_scale_pre(int Rm, int type=0, uint32_t shift=0, int W=0);
|
||||
virtual uint32_t reg_scale_post(int Rm, int type=0, uint32_t shift=0);
|
||||
|
||||
// LDRH/LDRSB/LDRSH/STRH
|
||||
// (immediate and Rm can be negative, which indicates U=0)
|
||||
virtual uint32_t immed8_pre(int32_t immed8, int W=0);
|
||||
virtual uint32_t immed8_post(int32_t immed8);
|
||||
virtual uint32_t reg_pre(int Rm, int W=0);
|
||||
virtual uint32_t reg_post(int Rm);
|
||||
|
||||
|
||||
virtual void dataProcessing(int opcode, int cc, int s,
|
||||
int Rd, int Rn,
|
||||
uint32_t Op2);
|
||||
|
@ -83,21 +114,23 @@ public:
|
|||
virtual uint32_t* pcForLabel(const char* label);
|
||||
|
||||
virtual void LDR (int cc, int Rd,
|
||||
int Rn, uint32_t offset = immed12_pre(0));
|
||||
int Rn, uint32_t offset = __immed12_pre(0));
|
||||
virtual void LDRB(int cc, int Rd,
|
||||
int Rn, uint32_t offset = immed12_pre(0));
|
||||
int Rn, uint32_t offset = __immed12_pre(0));
|
||||
virtual void STR (int cc, int Rd,
|
||||
int Rn, uint32_t offset = immed12_pre(0));
|
||||
int Rn, uint32_t offset = __immed12_pre(0));
|
||||
virtual void STRB(int cc, int Rd,
|
||||
int Rn, uint32_t offset = immed12_pre(0));
|
||||
int Rn, uint32_t offset = __immed12_pre(0));
|
||||
virtual void LDRH (int cc, int Rd,
|
||||
int Rn, uint32_t offset = immed8_pre(0));
|
||||
int Rn, uint32_t offset = __immed8_pre(0));
|
||||
virtual void LDRSB(int cc, int Rd,
|
||||
int Rn, uint32_t offset = immed8_pre(0));
|
||||
int Rn, uint32_t offset = __immed8_pre(0));
|
||||
virtual void LDRSH(int cc, int Rd,
|
||||
int Rn, uint32_t offset = immed8_pre(0));
|
||||
int Rn, uint32_t offset = __immed8_pre(0));
|
||||
virtual void STRH (int cc, int Rd,
|
||||
int Rn, uint32_t offset = immed8_pre(0));
|
||||
int Rn, uint32_t offset = __immed8_pre(0));
|
||||
|
||||
|
||||
virtual void LDM(int cc, int dir,
|
||||
int Rn, int W, uint32_t reg_list);
|
||||
virtual void STM(int cc, int dir,
|
||||
|
|
|
@ -32,77 +32,15 @@ ARMAssemblerInterface::~ARMAssemblerInterface()
|
|||
{
|
||||
}
|
||||
|
||||
int ARMAssemblerInterface::buildImmediate(
|
||||
uint32_t immediate, uint32_t& rot, uint32_t& imm)
|
||||
{
|
||||
rot = 0;
|
||||
imm = immediate;
|
||||
if (imm > 0x7F) { // skip the easy cases
|
||||
while (!(imm&3) || (imm&0xFC000000)) {
|
||||
uint32_t newval;
|
||||
newval = imm >> 2;
|
||||
newval |= (imm&3) << 30;
|
||||
imm = newval;
|
||||
rot += 2;
|
||||
if (rot == 32) {
|
||||
rot = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
rot = (16 - (rot>>1)) & 0xF;
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
if (imm>=0x100)
|
||||
return -EINVAL;
|
||||
// The following two functions are static and used for initializers
|
||||
// in the original ARM code. The above versions (without __), are now
|
||||
// virtual, and can be overridden in the MIPS code. But since these are
|
||||
// needed at initialization time, they must be static. Not thrilled with
|
||||
// this implementation, but it works...
|
||||
|
||||
if (((imm>>(rot<<1)) | (imm<<(32-(rot<<1)))) != immediate)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// shifters...
|
||||
|
||||
bool ARMAssemblerInterface::isValidImmediate(uint32_t immediate)
|
||||
{
|
||||
uint32_t rot, imm;
|
||||
return buildImmediate(immediate, rot, imm) == 0;
|
||||
}
|
||||
|
||||
uint32_t ARMAssemblerInterface::imm(uint32_t immediate)
|
||||
{
|
||||
uint32_t rot, imm;
|
||||
int err = buildImmediate(immediate, rot, imm);
|
||||
|
||||
LOG_ALWAYS_FATAL_IF(err==-EINVAL,
|
||||
"immediate %08x cannot be encoded",
|
||||
immediate);
|
||||
|
||||
LOG_ALWAYS_FATAL_IF(err,
|
||||
"immediate (%08x) encoding bogus!",
|
||||
immediate);
|
||||
|
||||
return (1<<25) | (rot<<8) | imm;
|
||||
}
|
||||
|
||||
uint32_t ARMAssemblerInterface::reg_imm(int Rm, int type, uint32_t shift)
|
||||
{
|
||||
return ((shift&0x1F)<<7) | ((type&0x3)<<5) | (Rm&0xF);
|
||||
}
|
||||
|
||||
uint32_t ARMAssemblerInterface::reg_rrx(int Rm)
|
||||
{
|
||||
return (ROR<<5) | (Rm&0xF);
|
||||
}
|
||||
|
||||
uint32_t ARMAssemblerInterface::reg_reg(int Rm, int type, int Rs)
|
||||
{
|
||||
return ((Rs&0xF)<<8) | ((type&0x3)<<5) | (1<<4) | (Rm&0xF);
|
||||
}
|
||||
|
||||
// addressing modes...
|
||||
// LDR(B)/STR(B)/PLD (immediate and Rm can be negative, which indicate U=0)
|
||||
uint32_t ARMAssemblerInterface::immed12_pre(int32_t immed12, int W)
|
||||
uint32_t ARMAssemblerInterface::__immed12_pre(int32_t immed12, int W)
|
||||
{
|
||||
LOG_ALWAYS_FATAL_IF(abs(immed12) >= 0x800,
|
||||
"LDR(B)/STR(B)/PLD immediate too big (%08x)",
|
||||
|
@ -111,30 +49,7 @@ uint32_t ARMAssemblerInterface::immed12_pre(int32_t immed12, int W)
|
|||
((W&1)<<21) | (abs(immed12)&0x7FF);
|
||||
}
|
||||
|
||||
uint32_t ARMAssemblerInterface::immed12_post(int32_t immed12)
|
||||
{
|
||||
LOG_ALWAYS_FATAL_IF(abs(immed12) >= 0x800,
|
||||
"LDR(B)/STR(B)/PLD immediate too big (%08x)",
|
||||
immed12);
|
||||
|
||||
return (((uint32_t(immed12)>>31)^1)<<23) | (abs(immed12)&0x7FF);
|
||||
}
|
||||
|
||||
uint32_t ARMAssemblerInterface::reg_scale_pre(int Rm, int type,
|
||||
uint32_t shift, int W)
|
||||
{
|
||||
return (1<<25) | (1<<24) |
|
||||
(((uint32_t(Rm)>>31)^1)<<23) | ((W&1)<<21) |
|
||||
reg_imm(abs(Rm), type, shift);
|
||||
}
|
||||
|
||||
uint32_t ARMAssemblerInterface::reg_scale_post(int Rm, int type, uint32_t shift)
|
||||
{
|
||||
return (1<<25) | (((uint32_t(Rm)>>31)^1)<<23) | reg_imm(abs(Rm), type, shift);
|
||||
}
|
||||
|
||||
// LDRH/LDRSB/LDRSH/STRH (immediate and Rm can be negative, which indicate U=0)
|
||||
uint32_t ARMAssemblerInterface::immed8_pre(int32_t immed8, int W)
|
||||
uint32_t ARMAssemblerInterface::__immed8_pre(int32_t immed8, int W)
|
||||
{
|
||||
uint32_t offset = abs(immed8);
|
||||
|
||||
|
@ -146,28 +61,6 @@ uint32_t ARMAssemblerInterface::immed8_pre(int32_t immed8, int W)
|
|||
((W&1)<<21) | (((offset&0xF0)<<4)|(offset&0xF));
|
||||
}
|
||||
|
||||
uint32_t ARMAssemblerInterface::immed8_post(int32_t immed8)
|
||||
{
|
||||
uint32_t offset = abs(immed8);
|
||||
|
||||
LOG_ALWAYS_FATAL_IF(abs(immed8) >= 0x100,
|
||||
"LDRH/LDRSB/LDRSH/STRH immediate too big (%08x)",
|
||||
immed8);
|
||||
|
||||
return (1<<22) | (((uint32_t(immed8)>>31)^1)<<23) |
|
||||
(((offset&0xF0)<<4) | (offset&0xF));
|
||||
}
|
||||
|
||||
uint32_t ARMAssemblerInterface::reg_pre(int Rm, int W)
|
||||
{
|
||||
return (1<<24) | (((uint32_t(Rm)>>31)^1)<<23) | ((W&1)<<21) | (abs(Rm)&0xF);
|
||||
}
|
||||
|
||||
uint32_t ARMAssemblerInterface::reg_post(int Rm)
|
||||
{
|
||||
return (((uint32_t(Rm)>>31)^1)<<23) | (abs(Rm)&0xF);
|
||||
}
|
||||
|
||||
|
||||
}; // namespace android
|
||||
|
||||
|
|
|
@ -62,33 +62,40 @@ public:
|
|||
LSAVED = LR4|LR5|LR6|LR7|LR8|LR9|LR10|LR11 | LLR
|
||||
};
|
||||
|
||||
enum {
|
||||
CODEGEN_ARCH_ARM = 1, CODEGEN_ARCH_MIPS
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// shifters and addressing modes
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
// shifters...
|
||||
static bool isValidImmediate(uint32_t immed);
|
||||
static int buildImmediate(uint32_t i, uint32_t& rot, uint32_t& imm);
|
||||
// these static versions are used for initializers on LDxx/STxx below
|
||||
static uint32_t __immed12_pre(int32_t immed12, int W=0);
|
||||
static uint32_t __immed8_pre(int32_t immed12, int W=0);
|
||||
|
||||
static uint32_t imm(uint32_t immediate);
|
||||
static uint32_t reg_imm(int Rm, int type, uint32_t shift);
|
||||
static uint32_t reg_rrx(int Rm);
|
||||
static uint32_t reg_reg(int Rm, int type, int Rs);
|
||||
virtual bool isValidImmediate(uint32_t immed) = 0;
|
||||
virtual int buildImmediate(uint32_t i, uint32_t& rot, uint32_t& imm) = 0;
|
||||
|
||||
virtual uint32_t imm(uint32_t immediate) = 0;
|
||||
virtual uint32_t reg_imm(int Rm, int type, uint32_t shift) = 0;
|
||||
virtual uint32_t reg_rrx(int Rm) = 0;
|
||||
virtual uint32_t reg_reg(int Rm, int type, int Rs) = 0;
|
||||
|
||||
// addressing modes...
|
||||
// LDR(B)/STR(B)/PLD
|
||||
// (immediate and Rm can be negative, which indicates U=0)
|
||||
static uint32_t immed12_pre(int32_t immed12, int W=0);
|
||||
static uint32_t immed12_post(int32_t immed12);
|
||||
static uint32_t reg_scale_pre(int Rm, int type=0, uint32_t shift=0, int W=0);
|
||||
static uint32_t reg_scale_post(int Rm, int type=0, uint32_t shift=0);
|
||||
virtual uint32_t immed12_pre(int32_t immed12, int W=0) = 0;
|
||||
virtual uint32_t immed12_post(int32_t immed12) = 0;
|
||||
virtual uint32_t reg_scale_pre(int Rm, int type=0, uint32_t shift=0, int W=0) = 0;
|
||||
virtual uint32_t reg_scale_post(int Rm, int type=0, uint32_t shift=0) = 0;
|
||||
|
||||
// LDRH/LDRSB/LDRSH/STRH
|
||||
// (immediate and Rm can be negative, which indicates U=0)
|
||||
static uint32_t immed8_pre(int32_t immed8, int W=0);
|
||||
static uint32_t immed8_post(int32_t immed8);
|
||||
static uint32_t reg_pre(int Rm, int W=0);
|
||||
static uint32_t reg_post(int Rm);
|
||||
virtual uint32_t immed8_pre(int32_t immed8, int W=0) = 0;
|
||||
virtual uint32_t immed8_post(int32_t immed8) = 0;
|
||||
virtual uint32_t reg_pre(int Rm, int W=0) = 0;
|
||||
virtual uint32_t reg_post(int Rm) = 0;
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// basic instructions & code generation
|
||||
|
@ -98,6 +105,7 @@ public:
|
|||
virtual void reset() = 0;
|
||||
virtual int generate(const char* name) = 0;
|
||||
virtual void disassemble(const char* name) = 0;
|
||||
virtual int getCodegenArch() = 0;
|
||||
|
||||
// construct prolog and epilog
|
||||
virtual void prolog() = 0;
|
||||
|
@ -143,22 +151,22 @@ public:
|
|||
|
||||
// data transfer...
|
||||
virtual void LDR (int cc, int Rd,
|
||||
int Rn, uint32_t offset = immed12_pre(0)) = 0;
|
||||
int Rn, uint32_t offset = __immed12_pre(0)) = 0;
|
||||
virtual void LDRB(int cc, int Rd,
|
||||
int Rn, uint32_t offset = immed12_pre(0)) = 0;
|
||||
int Rn, uint32_t offset = __immed12_pre(0)) = 0;
|
||||
virtual void STR (int cc, int Rd,
|
||||
int Rn, uint32_t offset = immed12_pre(0)) = 0;
|
||||
int Rn, uint32_t offset = __immed12_pre(0)) = 0;
|
||||
virtual void STRB(int cc, int Rd,
|
||||
int Rn, uint32_t offset = immed12_pre(0)) = 0;
|
||||
int Rn, uint32_t offset = __immed12_pre(0)) = 0;
|
||||
|
||||
virtual void LDRH (int cc, int Rd,
|
||||
int Rn, uint32_t offset = immed8_pre(0)) = 0;
|
||||
int Rn, uint32_t offset = __immed8_pre(0)) = 0;
|
||||
virtual void LDRSB(int cc, int Rd,
|
||||
int Rn, uint32_t offset = immed8_pre(0)) = 0;
|
||||
int Rn, uint32_t offset = __immed8_pre(0)) = 0;
|
||||
virtual void LDRSH(int cc, int Rd,
|
||||
int Rn, uint32_t offset = immed8_pre(0)) = 0;
|
||||
int Rn, uint32_t offset = __immed8_pre(0)) = 0;
|
||||
virtual void STRH (int cc, int Rd,
|
||||
int Rn, uint32_t offset = immed8_pre(0)) = 0;
|
||||
int Rn, uint32_t offset = __immed8_pre(0)) = 0;
|
||||
|
||||
// block data transfer...
|
||||
virtual void LDM(int cc, int dir,
|
||||
|
|
|
@ -55,6 +55,10 @@ int ARMAssemblerProxy::generate(const char* name) {
|
|||
void ARMAssemblerProxy::disassemble(const char* name) {
|
||||
return mTarget->disassemble(name);
|
||||
}
|
||||
int ARMAssemblerProxy::getCodegenArch()
|
||||
{
|
||||
return mTarget->getCodegenArch();
|
||||
}
|
||||
void ARMAssemblerProxy::prolog() {
|
||||
mTarget->prolog();
|
||||
}
|
||||
|
@ -66,6 +70,93 @@ void ARMAssemblerProxy::comment(const char* string) {
|
|||
}
|
||||
|
||||
|
||||
|
||||
// addressing modes
|
||||
|
||||
bool ARMAssemblerProxy::isValidImmediate(uint32_t immed)
|
||||
{
|
||||
return mTarget->isValidImmediate(immed);
|
||||
}
|
||||
|
||||
int ARMAssemblerProxy::buildImmediate(uint32_t i, uint32_t& rot, uint32_t& imm)
|
||||
{
|
||||
return mTarget->buildImmediate(i, rot, imm);
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint32_t ARMAssemblerProxy::imm(uint32_t immediate)
|
||||
{
|
||||
return mTarget->imm(immediate);
|
||||
}
|
||||
|
||||
uint32_t ARMAssemblerProxy::reg_imm(int Rm, int type, uint32_t shift)
|
||||
{
|
||||
return mTarget->reg_imm(Rm, type, shift);
|
||||
}
|
||||
|
||||
uint32_t ARMAssemblerProxy::reg_rrx(int Rm)
|
||||
{
|
||||
return mTarget->reg_rrx(Rm);
|
||||
}
|
||||
|
||||
uint32_t ARMAssemblerProxy::reg_reg(int Rm, int type, int Rs)
|
||||
{
|
||||
return mTarget->reg_reg(Rm, type, Rs);
|
||||
}
|
||||
|
||||
|
||||
// addressing modes...
|
||||
// LDR(B)/STR(B)/PLD
|
||||
// (immediate and Rm can be negative, which indicates U=0)
|
||||
uint32_t ARMAssemblerProxy::immed12_pre(int32_t immed12, int W)
|
||||
{
|
||||
return mTarget->immed12_pre(immed12, W);
|
||||
}
|
||||
|
||||
uint32_t ARMAssemblerProxy::immed12_post(int32_t immed12)
|
||||
{
|
||||
return mTarget->immed12_post(immed12);
|
||||
}
|
||||
|
||||
uint32_t ARMAssemblerProxy::reg_scale_pre(int Rm, int type, uint32_t shift, int W)
|
||||
{
|
||||
return mTarget->reg_scale_pre(Rm, type, shift, W);
|
||||
}
|
||||
|
||||
uint32_t ARMAssemblerProxy::reg_scale_post(int Rm, int type, uint32_t shift)
|
||||
{
|
||||
return mTarget->reg_scale_post(Rm, type, shift);
|
||||
}
|
||||
|
||||
|
||||
// LDRH/LDRSB/LDRSH/STRH
|
||||
// (immediate and Rm can be negative, which indicates U=0)
|
||||
uint32_t ARMAssemblerProxy::immed8_pre(int32_t immed8, int W)
|
||||
{
|
||||
return mTarget->immed8_pre(immed8, W);
|
||||
}
|
||||
|
||||
uint32_t ARMAssemblerProxy::immed8_post(int32_t immed8)
|
||||
{
|
||||
return mTarget->immed8_post(immed8);
|
||||
}
|
||||
|
||||
uint32_t ARMAssemblerProxy::reg_pre(int Rm, int W)
|
||||
{
|
||||
return mTarget->reg_pre(Rm, W);
|
||||
}
|
||||
|
||||
uint32_t ARMAssemblerProxy::reg_post(int Rm)
|
||||
{
|
||||
return mTarget->reg_post(Rm);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
void ARMAssemblerProxy::dataProcessing( int opcode, int cc, int s,
|
||||
int Rd, int Rn, uint32_t Op2)
|
||||
{
|
||||
|
|
|
@ -42,11 +42,40 @@ public:
|
|||
virtual void reset();
|
||||
virtual int generate(const char* name);
|
||||
virtual void disassemble(const char* name);
|
||||
virtual int getCodegenArch();
|
||||
|
||||
virtual void prolog();
|
||||
virtual void epilog(uint32_t touched);
|
||||
virtual void comment(const char* string);
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// shifters and addressing modes
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
virtual bool isValidImmediate(uint32_t immed);
|
||||
virtual int buildImmediate(uint32_t i, uint32_t& rot, uint32_t& imm);
|
||||
|
||||
virtual uint32_t imm(uint32_t immediate);
|
||||
virtual uint32_t reg_imm(int Rm, int type, uint32_t shift);
|
||||
virtual uint32_t reg_rrx(int Rm);
|
||||
virtual uint32_t reg_reg(int Rm, int type, int Rs);
|
||||
|
||||
// addressing modes...
|
||||
// LDR(B)/STR(B)/PLD
|
||||
// (immediate and Rm can be negative, which indicates U=0)
|
||||
virtual uint32_t immed12_pre(int32_t immed12, int W=0);
|
||||
virtual uint32_t immed12_post(int32_t immed12);
|
||||
virtual uint32_t reg_scale_pre(int Rm, int type=0, uint32_t shift=0, int W=0);
|
||||
virtual uint32_t reg_scale_post(int Rm, int type=0, uint32_t shift=0);
|
||||
|
||||
// LDRH/LDRSB/LDRSH/STRH
|
||||
// (immediate and Rm can be negative, which indicates U=0)
|
||||
virtual uint32_t immed8_pre(int32_t immed8, int W=0);
|
||||
virtual uint32_t immed8_post(int32_t immed8);
|
||||
virtual uint32_t reg_pre(int Rm, int W=0);
|
||||
virtual uint32_t reg_post(int Rm);
|
||||
|
||||
|
||||
virtual void dataProcessing(int opcode, int cc, int s,
|
||||
int Rd, int Rn,
|
||||
uint32_t Op2);
|
||||
|
@ -73,21 +102,21 @@ public:
|
|||
uint32_t* pcForLabel(const char* label);
|
||||
|
||||
virtual void LDR (int cc, int Rd,
|
||||
int Rn, uint32_t offset = immed12_pre(0));
|
||||
int Rn, uint32_t offset = __immed12_pre(0));
|
||||
virtual void LDRB(int cc, int Rd,
|
||||
int Rn, uint32_t offset = immed12_pre(0));
|
||||
int Rn, uint32_t offset = __immed12_pre(0));
|
||||
virtual void STR (int cc, int Rd,
|
||||
int Rn, uint32_t offset = immed12_pre(0));
|
||||
int Rn, uint32_t offset = __immed12_pre(0));
|
||||
virtual void STRB(int cc, int Rd,
|
||||
int Rn, uint32_t offset = immed12_pre(0));
|
||||
int Rn, uint32_t offset = __immed12_pre(0));
|
||||
virtual void LDRH (int cc, int Rd,
|
||||
int Rn, uint32_t offset = immed8_pre(0));
|
||||
int Rn, uint32_t offset = __immed8_pre(0));
|
||||
virtual void LDRSB(int cc, int Rd,
|
||||
int Rn, uint32_t offset = immed8_pre(0));
|
||||
int Rn, uint32_t offset = __immed8_pre(0));
|
||||
virtual void LDRSH(int cc, int Rd,
|
||||
int Rn, uint32_t offset = immed8_pre(0));
|
||||
int Rn, uint32_t offset = __immed8_pre(0));
|
||||
virtual void STRH (int cc, int Rd,
|
||||
int Rn, uint32_t offset = immed8_pre(0));
|
||||
int Rn, uint32_t offset = __immed8_pre(0));
|
||||
virtual void LDM(int cc, int dir,
|
||||
int Rn, int W, uint32_t reg_list);
|
||||
virtual void STM(int cc, int dir,
|
||||
|
|
|
@ -36,6 +36,12 @@ namespace android {
|
|||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#if defined(__mips__)
|
||||
#include <asm/cachectl.h>
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
Assembly::Assembly(size_t size)
|
||||
|
@ -155,12 +161,12 @@ int CodeCache::cache( const AssemblyKeyBase& keyBase,
|
|||
mCacheInUse += assemblySize;
|
||||
mWhen++;
|
||||
// synchronize caches...
|
||||
#if defined(__arm__)
|
||||
#if defined(__arm__) || defined(__mips__)
|
||||
const long base = long(assembly->base());
|
||||
const long curr = base + long(assembly->size());
|
||||
err = cacheflush(base, curr, 0);
|
||||
ALOGE_IF(err, "__ARM_NR_cacheflush error %s\n",
|
||||
strerror(errno));
|
||||
ALOGE_IF(err, "cacheflush error %s\n",
|
||||
strerror(errno));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,8 @@ namespace android {
|
|||
// ----------------------------------------------------------------------------
|
||||
|
||||
GGLAssembler::GGLAssembler(ARMAssemblerInterface* target)
|
||||
: ARMAssemblerProxy(target), RegisterAllocator(), mOptLevel(7)
|
||||
: ARMAssemblerProxy(target),
|
||||
RegisterAllocator(ARMAssemblerProxy::getCodegenArch()), mOptLevel(7)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -230,7 +231,9 @@ int GGLAssembler::scanline_core(const needs_t& needs, context_t const* c)
|
|||
|
||||
// texel generation
|
||||
build_textures(parts, regs);
|
||||
}
|
||||
if (registerFile().status())
|
||||
return registerFile().status();
|
||||
}
|
||||
|
||||
if ((blending & (FACTOR_DST|BLEND_DST)) ||
|
||||
(mMasking && !mAllMasked) ||
|
||||
|
@ -890,6 +893,15 @@ void GGLAssembler::build_and_immediate(int d, int s, uint32_t mask, int bits)
|
|||
return;
|
||||
}
|
||||
|
||||
if (getCodegenArch() == CODEGEN_ARCH_MIPS) {
|
||||
// MIPS can do 16-bit imm in 1 instr, 32-bit in 3 instr
|
||||
// the below ' while (mask)' code is buggy on mips
|
||||
// since mips returns true on isValidImmediate()
|
||||
// then we get multiple AND instr (positive logic)
|
||||
AND( AL, 0, d, s, imm(mask) );
|
||||
return;
|
||||
}
|
||||
|
||||
int negative_logic = !isValidImmediate(mask);
|
||||
if (negative_logic) {
|
||||
mask = ~mask & size;
|
||||
|
@ -1002,6 +1014,15 @@ void GGLAssembler::base_offset(
|
|||
// cheezy register allocator...
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Modified to support MIPS processors, in a very simple way. We retain the
|
||||
// (Arm) limit of 16 total registers, but shift the mapping of those registers
|
||||
// from 0-15, to 2-17. Register 0 on Mips cannot be used as GP registers, and
|
||||
// register 1 has a traditional use as a temp).
|
||||
|
||||
RegisterAllocator::RegisterAllocator(int arch) : mRegs(arch)
|
||||
{
|
||||
}
|
||||
|
||||
void RegisterAllocator::reset()
|
||||
{
|
||||
mRegs.reset();
|
||||
|
@ -1029,16 +1050,22 @@ RegisterAllocator::RegisterFile& RegisterAllocator::registerFile()
|
|||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
RegisterAllocator::RegisterFile::RegisterFile()
|
||||
: mRegs(0), mTouched(0), mStatus(0)
|
||||
RegisterAllocator::RegisterFile::RegisterFile(int codegen_arch)
|
||||
: mRegs(0), mTouched(0), mStatus(0), mArch(codegen_arch), mRegisterOffset(0)
|
||||
{
|
||||
if (mArch == ARMAssemblerInterface::CODEGEN_ARCH_MIPS) {
|
||||
mRegisterOffset = 2; // ARM has regs 0..15, MIPS offset to 2..17
|
||||
}
|
||||
reserve(ARMAssemblerInterface::SP);
|
||||
reserve(ARMAssemblerInterface::PC);
|
||||
}
|
||||
|
||||
RegisterAllocator::RegisterFile::RegisterFile(const RegisterFile& rhs)
|
||||
: mRegs(rhs.mRegs), mTouched(rhs.mTouched)
|
||||
RegisterAllocator::RegisterFile::RegisterFile(const RegisterFile& rhs, int codegen_arch)
|
||||
: mRegs(rhs.mRegs), mTouched(rhs.mTouched), mArch(codegen_arch), mRegisterOffset(0)
|
||||
{
|
||||
if (mArch == ARMAssemblerInterface::CODEGEN_ARCH_MIPS) {
|
||||
mRegisterOffset = 2; // ARM has regs 0..15, MIPS offset to 2..17
|
||||
}
|
||||
}
|
||||
|
||||
RegisterAllocator::RegisterFile::~RegisterFile()
|
||||
|
@ -1057,8 +1084,12 @@ void RegisterAllocator::RegisterFile::reset()
|
|||
reserve(ARMAssemblerInterface::PC);
|
||||
}
|
||||
|
||||
// RegisterFile::reserve() take a register parameter in the
|
||||
// range 0-15 (Arm compatible), but on a Mips processor, will
|
||||
// return the actual allocated register in the range 2-17.
|
||||
int RegisterAllocator::RegisterFile::reserve(int reg)
|
||||
{
|
||||
reg += mRegisterOffset;
|
||||
LOG_ALWAYS_FATAL_IF(isUsed(reg),
|
||||
"reserving register %d, but already in use",
|
||||
reg);
|
||||
|
@ -1067,6 +1098,7 @@ int RegisterAllocator::RegisterFile::reserve(int reg)
|
|||
return reg;
|
||||
}
|
||||
|
||||
// This interface uses regMask in range 2-17 on MIPS, no translation.
|
||||
void RegisterAllocator::RegisterFile::reserveSeveral(uint32_t regMask)
|
||||
{
|
||||
mRegs |= regMask;
|
||||
|
@ -1075,7 +1107,7 @@ void RegisterAllocator::RegisterFile::reserveSeveral(uint32_t regMask)
|
|||
|
||||
int RegisterAllocator::RegisterFile::isUsed(int reg) const
|
||||
{
|
||||
LOG_ALWAYS_FATAL_IF(reg>=16, "invalid register %d", reg);
|
||||
LOG_ALWAYS_FATAL_IF(reg>=16+(int)mRegisterOffset, "invalid register %d", reg);
|
||||
return mRegs & (1<<reg);
|
||||
}
|
||||
|
||||
|
@ -1086,10 +1118,10 @@ int RegisterAllocator::RegisterFile::obtain()
|
|||
6, 7, 8, 9,
|
||||
10, 11 };
|
||||
const int nbreg = sizeof(priorityList);
|
||||
int i, r;
|
||||
int i, r, reg;
|
||||
for (i=0 ; i<nbreg ; i++) {
|
||||
r = priorityList[i];
|
||||
if (!isUsed(r)) {
|
||||
if (!isUsed(r + mRegisterOffset)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1102,18 +1134,20 @@ int RegisterAllocator::RegisterFile::obtain()
|
|||
// the code will never be run anyway.
|
||||
return ARMAssemblerInterface::SP;
|
||||
}
|
||||
reserve(r);
|
||||
return r;
|
||||
reg = reserve(r); // Param in Arm range 0-15, returns range 2-17 on Mips.
|
||||
return reg;
|
||||
}
|
||||
|
||||
bool RegisterAllocator::RegisterFile::hasFreeRegs() const
|
||||
{
|
||||
return ((mRegs & 0xFFFF) == 0xFFFF) ? false : true;
|
||||
uint32_t regs = mRegs >> mRegisterOffset; // MIPS fix.
|
||||
return ((regs & 0xFFFF) == 0xFFFF) ? false : true;
|
||||
}
|
||||
|
||||
int RegisterAllocator::RegisterFile::countFreeRegs() const
|
||||
{
|
||||
int f = ~mRegs & 0xFFFF;
|
||||
uint32_t regs = mRegs >> mRegisterOffset; // MIPS fix.
|
||||
int f = ~regs & 0xFFFF;
|
||||
// now count number of 1
|
||||
f = (f & 0x5555) + ((f>>1) & 0x5555);
|
||||
f = (f & 0x3333) + ((f>>2) & 0x3333);
|
||||
|
@ -1124,18 +1158,24 @@ int RegisterAllocator::RegisterFile::countFreeRegs() const
|
|||
|
||||
void RegisterAllocator::RegisterFile::recycle(int reg)
|
||||
{
|
||||
LOG_FATAL_IF(!isUsed(reg),
|
||||
"recycling unallocated register %d",
|
||||
reg);
|
||||
// commented out, since common failure of running out of regs
|
||||
// triggers this assertion. Since the code is not execectued
|
||||
// in that case, it does not matter. No reason to FATAL err.
|
||||
// LOG_FATAL_IF(!isUsed(reg),
|
||||
// "recycling unallocated register %d",
|
||||
// reg);
|
||||
mRegs &= ~(1<<reg);
|
||||
}
|
||||
|
||||
void RegisterAllocator::RegisterFile::recycleSeveral(uint32_t regMask)
|
||||
{
|
||||
LOG_FATAL_IF((mRegs & regMask)!=regMask,
|
||||
"recycling unallocated registers "
|
||||
"(recycle=%08x, allocated=%08x, unallocated=%08x)",
|
||||
regMask, mRegs, mRegs®Mask);
|
||||
// commented out, since common failure of running out of regs
|
||||
// triggers this assertion. Since the code is not execectued
|
||||
// in that case, it does not matter. No reason to FATAL err.
|
||||
// LOG_FATAL_IF((mRegs & regMask)!=regMask,
|
||||
// "recycling unallocated registers "
|
||||
// "(recycle=%08x, allocated=%08x, unallocated=%08x)",
|
||||
// regMask, mRegs, mRegs®Mask);
|
||||
mRegs &= ~regMask;
|
||||
}
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ class RegisterAllocator
|
|||
public:
|
||||
class RegisterFile;
|
||||
|
||||
RegisterAllocator(int arch);
|
||||
RegisterFile& registerFile();
|
||||
int reserveReg(int reg);
|
||||
int obtainReg();
|
||||
|
@ -52,8 +53,8 @@ public:
|
|||
class RegisterFile
|
||||
{
|
||||
public:
|
||||
RegisterFile();
|
||||
RegisterFile(const RegisterFile& rhs);
|
||||
RegisterFile(int arch);
|
||||
RegisterFile(const RegisterFile& rhs, int arch);
|
||||
~RegisterFile();
|
||||
|
||||
void reset();
|
||||
|
@ -86,6 +87,9 @@ public:
|
|||
uint32_t mRegs;
|
||||
uint32_t mTouched;
|
||||
uint32_t mStatus;
|
||||
int mArch;
|
||||
uint32_t mRegisterOffset; // lets reg alloc use 2..17 for mips
|
||||
// while arm uses 0..15
|
||||
};
|
||||
|
||||
class Scratch
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,555 @@
|
|||
/* libs/pixelflinger/codeflinger/MIPSAssembler.h
|
||||
**
|
||||
** Copyright 2012, The Android Open Source Project
|
||||
**
|
||||
** Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
|
||||
**
|
||||
** Unless required by applicable law or agreed to in writing, software
|
||||
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
** See the License for the specific language governing permissions and
|
||||
** limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ANDROID_MIPSASSEMBLER_H
|
||||
#define ANDROID_MIPSASSEMBLER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <utils/Vector.h>
|
||||
#include <utils/KeyedVector.h>
|
||||
|
||||
#include "tinyutils/smartpointer.h"
|
||||
#include "codeflinger/ARMAssemblerInterface.h"
|
||||
#include "codeflinger/CodeCache.h"
|
||||
|
||||
namespace android {
|
||||
|
||||
class MIPSAssembler; // forward reference
|
||||
|
||||
// this class mimics ARMAssembler interface
|
||||
// intent is to translate each ARM instruction to 1 or more MIPS instr
|
||||
// implementation calls MIPSAssembler class to generate mips code
|
||||
class ArmToMipsAssembler : public ARMAssemblerInterface
|
||||
{
|
||||
public:
|
||||
ArmToMipsAssembler(const sp<Assembly>& assembly,
|
||||
char *abuf = 0, int linesz = 0, int instr_count = 0);
|
||||
virtual ~ArmToMipsAssembler();
|
||||
|
||||
uint32_t* base() const;
|
||||
uint32_t* pc() const;
|
||||
void disassemble(const char* name);
|
||||
|
||||
virtual void reset();
|
||||
|
||||
virtual int generate(const char* name);
|
||||
virtual int getCodegenArch();
|
||||
|
||||
virtual void prolog();
|
||||
virtual void epilog(uint32_t touched);
|
||||
virtual void comment(const char* string);
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// shifters and addressing modes
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
// shifters...
|
||||
virtual bool isValidImmediate(uint32_t immed);
|
||||
virtual int buildImmediate(uint32_t i, uint32_t& rot, uint32_t& imm);
|
||||
|
||||
virtual uint32_t imm(uint32_t immediate);
|
||||
virtual uint32_t reg_imm(int Rm, int type, uint32_t shift);
|
||||
virtual uint32_t reg_rrx(int Rm);
|
||||
virtual uint32_t reg_reg(int Rm, int type, int Rs);
|
||||
|
||||
// addressing modes...
|
||||
// LDR(B)/STR(B)/PLD
|
||||
// (immediate and Rm can be negative, which indicates U=0)
|
||||
virtual uint32_t immed12_pre(int32_t immed12, int W=0);
|
||||
virtual uint32_t immed12_post(int32_t immed12);
|
||||
virtual uint32_t reg_scale_pre(int Rm, int type=0, uint32_t shift=0, int W=0);
|
||||
virtual uint32_t reg_scale_post(int Rm, int type=0, uint32_t shift=0);
|
||||
|
||||
// LDRH/LDRSB/LDRSH/STRH
|
||||
// (immediate and Rm can be negative, which indicates U=0)
|
||||
virtual uint32_t immed8_pre(int32_t immed8, int W=0);
|
||||
virtual uint32_t immed8_post(int32_t immed8);
|
||||
virtual uint32_t reg_pre(int Rm, int W=0);
|
||||
virtual uint32_t reg_post(int Rm);
|
||||
|
||||
|
||||
|
||||
|
||||
virtual void dataProcessing(int opcode, int cc, int s,
|
||||
int Rd, int Rn,
|
||||
uint32_t Op2);
|
||||
virtual void MLA(int cc, int s,
|
||||
int Rd, int Rm, int Rs, int Rn);
|
||||
virtual void MUL(int cc, int s,
|
||||
int Rd, int Rm, int Rs);
|
||||
virtual void UMULL(int cc, int s,
|
||||
int RdLo, int RdHi, int Rm, int Rs);
|
||||
virtual void UMUAL(int cc, int s,
|
||||
int RdLo, int RdHi, int Rm, int Rs);
|
||||
virtual void SMULL(int cc, int s,
|
||||
int RdLo, int RdHi, int Rm, int Rs);
|
||||
virtual void SMUAL(int cc, int s,
|
||||
int RdLo, int RdHi, int Rm, int Rs);
|
||||
|
||||
virtual void B(int cc, uint32_t* pc);
|
||||
virtual void BL(int cc, uint32_t* pc);
|
||||
virtual void BX(int cc, int Rn);
|
||||
virtual void label(const char* theLabel);
|
||||
virtual void B(int cc, const char* label);
|
||||
virtual void BL(int cc, const char* label);
|
||||
|
||||
virtual uint32_t* pcForLabel(const char* label);
|
||||
|
||||
virtual void LDR (int cc, int Rd,
|
||||
int Rn, uint32_t offset = 0);
|
||||
virtual void LDRB(int cc, int Rd,
|
||||
int Rn, uint32_t offset = 0);
|
||||
virtual void STR (int cc, int Rd,
|
||||
int Rn, uint32_t offset = 0);
|
||||
virtual void STRB(int cc, int Rd,
|
||||
int Rn, uint32_t offset = 0);
|
||||
virtual void LDRH (int cc, int Rd,
|
||||
int Rn, uint32_t offset = 0);
|
||||
virtual void LDRSB(int cc, int Rd,
|
||||
int Rn, uint32_t offset = 0);
|
||||
virtual void LDRSH(int cc, int Rd,
|
||||
int Rn, uint32_t offset = 0);
|
||||
virtual void STRH (int cc, int Rd,
|
||||
int Rn, uint32_t offset = 0);
|
||||
|
||||
virtual void LDM(int cc, int dir,
|
||||
int Rn, int W, uint32_t reg_list);
|
||||
virtual void STM(int cc, int dir,
|
||||
int Rn, int W, uint32_t reg_list);
|
||||
|
||||
virtual void SWP(int cc, int Rn, int Rd, int Rm);
|
||||
virtual void SWPB(int cc, int Rn, int Rd, int Rm);
|
||||
virtual void SWI(int cc, uint32_t comment);
|
||||
|
||||
virtual void PLD(int Rn, uint32_t offset);
|
||||
virtual void CLZ(int cc, int Rd, int Rm);
|
||||
virtual void QADD(int cc, int Rd, int Rm, int Rn);
|
||||
virtual void QDADD(int cc, int Rd, int Rm, int Rn);
|
||||
virtual void QSUB(int cc, int Rd, int Rm, int Rn);
|
||||
virtual void QDSUB(int cc, int Rd, int Rm, int Rn);
|
||||
virtual void SMUL(int cc, int xy,
|
||||
int Rd, int Rm, int Rs);
|
||||
virtual void SMULW(int cc, int y,
|
||||
int Rd, int Rm, int Rs);
|
||||
virtual void SMLA(int cc, int xy,
|
||||
int Rd, int Rm, int Rs, int Rn);
|
||||
virtual void SMLAL(int cc, int xy,
|
||||
int RdHi, int RdLo, int Rs, int Rm);
|
||||
virtual void SMLAW(int cc, int y,
|
||||
int Rd, int Rm, int Rs, int Rn);
|
||||
|
||||
// byte/half word extract...
|
||||
virtual void UXTB16(int cc, int Rd, int Rm, int rotate);
|
||||
|
||||
// bit manipulation...
|
||||
virtual void UBFX(int cc, int Rd, int Rn, int lsb, int width);
|
||||
|
||||
// this is some crap to share is MIPSAssembler class for debug
|
||||
char * mArmDisassemblyBuffer;
|
||||
int mArmLineLength;
|
||||
int mArmInstrCount;
|
||||
|
||||
int mInum; // current arm instuction number (0..n)
|
||||
uint32_t** mArmPC; // array: PC for 1st mips instr of
|
||||
// each translated ARM instr
|
||||
|
||||
|
||||
private:
|
||||
ArmToMipsAssembler(const ArmToMipsAssembler& rhs);
|
||||
ArmToMipsAssembler& operator = (const ArmToMipsAssembler& rhs);
|
||||
|
||||
void init_conditional_labels(void);
|
||||
|
||||
void protectConditionalOperands(int Rd);
|
||||
|
||||
// reg__tmp set to MIPS AT, reg 1
|
||||
int dataProcAdrModes(int op, int& source, bool sign = false, int reg_tmp = 1);
|
||||
|
||||
sp<Assembly> mAssembly;
|
||||
MIPSAssembler* mMips;
|
||||
|
||||
|
||||
enum misc_constants_t {
|
||||
ARM_MAX_INSTUCTIONS = 512 // based on ASSEMBLY_SCRATCH_SIZE
|
||||
};
|
||||
|
||||
enum {
|
||||
SRC_REG = 0,
|
||||
SRC_IMM,
|
||||
SRC_ERROR = -1
|
||||
};
|
||||
|
||||
enum addr_modes {
|
||||
// start above the range of legal mips reg #'s (0-31)
|
||||
AMODE_REG = 0x20,
|
||||
AMODE_IMM, AMODE_REG_IMM, // for data processing
|
||||
AMODE_IMM_12_PRE, AMODE_IMM_12_POST, // for load/store
|
||||
AMODE_REG_SCALE_PRE, AMODE_IMM_8_PRE,
|
||||
AMODE_IMM_8_POST, AMODE_REG_PRE,
|
||||
AMODE_UNSUPPORTED
|
||||
};
|
||||
|
||||
struct addr_mode_t { // address modes for current ARM instruction
|
||||
int reg;
|
||||
int stype;
|
||||
uint32_t value;
|
||||
bool writeback; // writeback the adr reg after modification
|
||||
} amode;
|
||||
|
||||
enum cond_types {
|
||||
CMP_COND = 1,
|
||||
SBIT_COND
|
||||
};
|
||||
|
||||
struct cond_mode_t { // conditional-execution info for current ARM instruction
|
||||
cond_types type;
|
||||
int r1;
|
||||
int r2;
|
||||
int labelnum;
|
||||
char label[100][10];
|
||||
} cond;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// This is the basic MIPS assembler, which just creates the opcodes in memory.
|
||||
// All the more complicated work is done in ArmToMipsAssember above.
|
||||
|
||||
class MIPSAssembler
|
||||
{
|
||||
public:
|
||||
MIPSAssembler(const sp<Assembly>& assembly, ArmToMipsAssembler *parent);
|
||||
virtual ~MIPSAssembler();
|
||||
|
||||
uint32_t* base() const;
|
||||
uint32_t* pc() const;
|
||||
void reset();
|
||||
|
||||
void disassemble(const char* name);
|
||||
|
||||
void prolog();
|
||||
void epilog(uint32_t touched);
|
||||
int generate(const char* name);
|
||||
void comment(const char* string);
|
||||
void label(const char* string);
|
||||
|
||||
// valid only after generate() has been called
|
||||
uint32_t* pcForLabel(const char* label);
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// MIPSAssemblerInterface...
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
#if 0
|
||||
#pragma mark -
|
||||
#pragma mark Arithmetic...
|
||||
#endif
|
||||
|
||||
void ADDU(int Rd, int Rs, int Rt);
|
||||
void ADDIU(int Rt, int Rs, int16_t imm);
|
||||
void SUBU(int Rd, int Rs, int Rt);
|
||||
void SUBIU(int Rt, int Rs, int16_t imm);
|
||||
void NEGU(int Rd, int Rs);
|
||||
void MUL(int Rd, int Rs, int Rt);
|
||||
void MULT(int Rs, int Rt); // dest is hi,lo
|
||||
void MULTU(int Rs, int Rt); // dest is hi,lo
|
||||
void MADD(int Rs, int Rt); // hi,lo = hi,lo + Rs * Rt
|
||||
void MADDU(int Rs, int Rt); // hi,lo = hi,lo + Rs * Rt
|
||||
void MSUB(int Rs, int Rt); // hi,lo = hi,lo - Rs * Rt
|
||||
void MSUBU(int Rs, int Rt); // hi,lo = hi,lo - Rs * Rt
|
||||
void SEB(int Rd, int Rt); // sign-extend byte (mips32r2)
|
||||
void SEH(int Rd, int Rt); // sign-extend half-word (mips32r2)
|
||||
|
||||
|
||||
#if 0
|
||||
#pragma mark -
|
||||
#pragma mark Comparisons...
|
||||
#endif
|
||||
|
||||
void SLT(int Rd, int Rs, int Rt);
|
||||
void SLTI(int Rt, int Rs, int16_t imm);
|
||||
void SLTU(int Rd, int Rs, int Rt);
|
||||
void SLTIU(int Rt, int Rs, int16_t imm);
|
||||
|
||||
|
||||
#if 0
|
||||
#pragma mark -
|
||||
#pragma mark Logical...
|
||||
#endif
|
||||
|
||||
void AND(int Rd, int Rs, int Rt);
|
||||
void ANDI(int Rd, int Rs, uint16_t imm);
|
||||
void OR(int Rd, int Rs, int Rt);
|
||||
void ORI(int Rt, int Rs, uint16_t imm);
|
||||
void NOR(int Rd, int Rs, int Rt);
|
||||
void NOT(int Rd, int Rs);
|
||||
void XOR(int Rd, int Rs, int Rt);
|
||||
void XORI(int Rt, int Rs, uint16_t imm);
|
||||
|
||||
void SLL(int Rd, int Rt, int shft);
|
||||
void SLLV(int Rd, int Rt, int Rs);
|
||||
void SRL(int Rd, int Rt, int shft);
|
||||
void SRLV(int Rd, int Rt, int Rs);
|
||||
void SRA(int Rd, int Rt, int shft);
|
||||
void SRAV(int Rd, int Rt, int Rs);
|
||||
void ROTR(int Rd, int Rt, int shft); // mips32r2
|
||||
void ROTRV(int Rd, int Rt, int Rs); // mips32r2
|
||||
void RORsyn(int Rd, int Rs, int Rt); // synthetic: d = s rotated by t
|
||||
void RORIsyn(int Rd, int Rt, int rot); // synthetic: d = s rotated by immed
|
||||
|
||||
void CLO(int Rd, int Rs);
|
||||
void CLZ(int Rd, int Rs);
|
||||
void WSBH(int Rd, int Rt);
|
||||
|
||||
|
||||
#if 0
|
||||
#pragma mark -
|
||||
#pragma mark Load/store...
|
||||
#endif
|
||||
|
||||
void LW(int Rt, int Rbase, int16_t offset);
|
||||
void SW(int Rt, int Rbase, int16_t offset);
|
||||
void LB(int Rt, int Rbase, int16_t offset);
|
||||
void LBU(int Rt, int Rbase, int16_t offset);
|
||||
void SB(int Rt, int Rbase, int16_t offset);
|
||||
void LH(int Rt, int Rbase, int16_t offset);
|
||||
void LHU(int Rt, int Rbase, int16_t offset);
|
||||
void SH(int Rt, int Rbase, int16_t offset);
|
||||
void LUI(int Rt, int16_t offset);
|
||||
|
||||
#if 0
|
||||
#pragma mark -
|
||||
#pragma mark Register moves...
|
||||
#endif
|
||||
|
||||
void MOVE(int Rd, int Rs);
|
||||
void MOVN(int Rd, int Rs, int Rt);
|
||||
void MOVZ(int Rd, int Rs, int Rt);
|
||||
void MFHI(int Rd);
|
||||
void MFLO(int Rd);
|
||||
void MTHI(int Rs);
|
||||
void MTLO(int Rs);
|
||||
|
||||
#if 0
|
||||
#pragma mark -
|
||||
#pragma mark Branch...
|
||||
#endif
|
||||
|
||||
void B(const char* label);
|
||||
void BEQ(int Rs, int Rt, const char* label);
|
||||
void BNE(int Rs, int Rt, const char* label);
|
||||
void BGEZ(int Rs, const char* label);
|
||||
void BGTZ(int Rs, const char* label);
|
||||
void BLEZ(int Rs, const char* label);
|
||||
void BLTZ(int Rs, const char* label);
|
||||
void JR(int Rs);
|
||||
|
||||
|
||||
#if 0
|
||||
#pragma mark -
|
||||
#pragma mark Synthesized Branch...
|
||||
#endif
|
||||
|
||||
// synthetic variants of above (using slt & friends)
|
||||
void BEQZ(int Rs, const char* label);
|
||||
void BNEZ(int Rs, const char* label);
|
||||
void BGE(int Rs, int Rt, const char* label);
|
||||
void BGEU(int Rs, int Rt, const char* label);
|
||||
void BGT(int Rs, int Rt, const char* label);
|
||||
void BGTU(int Rs, int Rt, const char* label);
|
||||
void BLE(int Rs, int Rt, const char* label);
|
||||
void BLEU(int Rs, int Rt, const char* label);
|
||||
void BLT(int Rs, int Rt, const char* label);
|
||||
void BLTU(int Rs, int Rt, const char* label);
|
||||
|
||||
#if 0
|
||||
#pragma mark -
|
||||
#pragma mark Misc...
|
||||
#endif
|
||||
|
||||
void NOP(void);
|
||||
void NOP2(void);
|
||||
void UNIMPL(void);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private:
|
||||
void string_detab(char *s);
|
||||
void string_pad(char *s, int padded_len);
|
||||
|
||||
ArmToMipsAssembler *mParent;
|
||||
sp<Assembly> mAssembly;
|
||||
uint32_t* mBase;
|
||||
uint32_t* mPC;
|
||||
uint32_t* mPrologPC;
|
||||
int64_t mDuration;
|
||||
#if defined(WITH_LIB_HARDWARE)
|
||||
bool mQemuTracing;
|
||||
#endif
|
||||
|
||||
struct branch_target_t {
|
||||
inline branch_target_t() : label(0), pc(0) { }
|
||||
inline branch_target_t(const char* l, uint32_t* p)
|
||||
: label(l), pc(p) { }
|
||||
const char* label;
|
||||
uint32_t* pc;
|
||||
};
|
||||
|
||||
Vector<branch_target_t> mBranchTargets;
|
||||
KeyedVector< const char*, uint32_t* > mLabels;
|
||||
KeyedVector< uint32_t*, const char* > mLabelsInverseMapping;
|
||||
KeyedVector< uint32_t*, const char* > mComments;
|
||||
|
||||
|
||||
|
||||
|
||||
// opcode field of all instructions
|
||||
enum opcode_field {
|
||||
spec_op, regimm_op, j_op, jal_op, // 00
|
||||
beq_op, bne_op, blez_op, bgtz_op,
|
||||
addi_op, addiu_op, slti_op, sltiu_op, // 08
|
||||
andi_op, ori_op, xori_op, lui_op,
|
||||
cop0_op, cop1_op, cop2_op, cop1x_op, // 10
|
||||
beql_op, bnel_op, blezl_op, bgtzl_op,
|
||||
daddi_op, daddiu_op, ldl_op, ldr_op, // 18
|
||||
spec2_op, jalx_op, mdmx_op, spec3_op,
|
||||
lb_op, lh_op, lwl_op, lw_op, // 20
|
||||
lbu_op, lhu_op, lwr_op, lwu_op,
|
||||
sb_op, sh_op, swl_op, sw_op, // 28
|
||||
sdl_op, sdr_op, swr_op, cache_op,
|
||||
ll_op, lwc1_op, lwc2_op, pref_op, // 30
|
||||
lld_op, ldc1_op, ldc2_op, ld_op,
|
||||
sc_op, swc1_op, swc2_op, rsrv_3b_op, // 38
|
||||
scd_op, sdc1_op, sdc2_op, sd_op
|
||||
};
|
||||
|
||||
|
||||
// func field for special opcode
|
||||
enum func_spec_op {
|
||||
sll_fn, movc_fn, srl_fn, sra_fn, // 00
|
||||
sllv_fn, pmon_fn, srlv_fn, srav_fn,
|
||||
jr_fn, jalr_fn, movz_fn, movn_fn, // 08
|
||||
syscall_fn, break_fn, spim_fn, sync_fn,
|
||||
mfhi_fn, mthi_fn, mflo_fn, mtlo_fn, // 10
|
||||
dsllv_fn, rsrv_spec_2, dsrlv_fn, dsrav_fn,
|
||||
mult_fn, multu_fn, div_fn, divu_fn, // 18
|
||||
dmult_fn, dmultu_fn, ddiv_fn, ddivu_fn,
|
||||
add_fn, addu_fn, sub_fn, subu_fn, // 20
|
||||
and_fn, or_fn, xor_fn, nor_fn,
|
||||
rsrv_spec_3, rsrv_spec_4, slt_fn, sltu_fn, // 28
|
||||
dadd_fn, daddu_fn, dsub_fn, dsubu_fn,
|
||||
tge_fn, tgeu_fn, tlt_fn, tltu_fn, // 30
|
||||
teq_fn, rsrv_spec_5, tne_fn, rsrv_spec_6,
|
||||
dsll_fn, rsrv_spec_7, dsrl_fn, dsra_fn, // 38
|
||||
dsll32_fn, rsrv_spec_8, dsrl32_fn, dsra32_fn
|
||||
};
|
||||
|
||||
// func field for spec2 opcode
|
||||
enum func_spec2_op {
|
||||
madd_fn, maddu_fn, mul_fn, rsrv_spec2_3,
|
||||
msub_fn, msubu_fn,
|
||||
clz_fn = 0x20, clo_fn,
|
||||
dclz_fn = 0x24, dclo_fn,
|
||||
sdbbp_fn = 0x3f
|
||||
};
|
||||
|
||||
// func field for spec3 opcode
|
||||
enum func_spec3_op {
|
||||
ext_fn, dextm_fn, dextu_fn, dext_fn,
|
||||
ins_fn, dinsm_fn, dinsu_fn, dins_fn,
|
||||
bshfl_fn = 0x20,
|
||||
dbshfl_fn = 0x24,
|
||||
rdhwr_fn = 0x3b
|
||||
};
|
||||
|
||||
// sa field for spec3 opcodes, with BSHFL function
|
||||
enum func_spec3_bshfl {
|
||||
wsbh_fn = 0x02,
|
||||
seb_fn = 0x10,
|
||||
seh_fn = 0x18
|
||||
};
|
||||
|
||||
// rt field of regimm opcodes.
|
||||
enum regimm_fn {
|
||||
bltz_fn, bgez_fn, bltzl_fn, bgezl_fn,
|
||||
rsrv_ri_fn4, rsrv_ri_fn5, rsrv_ri_fn6, rsrv_ri_fn7,
|
||||
tgei_fn, tgeiu_fn, tlti_fn, tltiu_fn,
|
||||
teqi_fn, rsrv_ri_fn_0d, tnei_fn, rsrv_ri_fn0f,
|
||||
bltzal_fn, bgezal_fn, bltzall_fn, bgezall_fn,
|
||||
bposge32_fn= 0x1c,
|
||||
synci_fn = 0x1f
|
||||
};
|
||||
|
||||
|
||||
// func field for mad opcodes (MIPS IV).
|
||||
enum mad_func {
|
||||
madd_fp_op = 0x08, msub_fp_op = 0x0a,
|
||||
nmadd_fp_op = 0x0c, nmsub_fp_op = 0x0e
|
||||
};
|
||||
|
||||
|
||||
enum mips_inst_shifts {
|
||||
OP_SHF = 26,
|
||||
JTARGET_SHF = 0,
|
||||
RS_SHF = 21,
|
||||
RT_SHF = 16,
|
||||
RD_SHF = 11,
|
||||
RE_SHF = 6,
|
||||
SA_SHF = RE_SHF, // synonym
|
||||
IMM_SHF = 0,
|
||||
FUNC_SHF = 0,
|
||||
|
||||
// mask values
|
||||
MSK_16 = 0xffff,
|
||||
|
||||
|
||||
CACHEOP_SHF = 18,
|
||||
CACHESEL_SHF = 16,
|
||||
};
|
||||
};
|
||||
|
||||
enum mips_regnames {
|
||||
R_zero = 0,
|
||||
R_at, R_v0, R_v1, R_a0, R_a1, R_a2, R_a3,
|
||||
R_t0, R_t1, R_t2, R_t3, R_t4, R_t5, R_t6, R_t7,
|
||||
R_s0, R_s1, R_s2, R_s3, R_s4, R_s5, R_s6, R_s7,
|
||||
R_t8, R_t9, R_k0, R_k1, R_gp, R_sp, R_s8, R_ra,
|
||||
R_lr = R_s8,
|
||||
|
||||
// arm regs 0-15 are mips regs 2-17 (meaning s0 & s1 are used)
|
||||
R_at2 = R_s2, // R_at2 = 18 = s2
|
||||
R_cmp = R_s3, // R_cmp = 19 = s3
|
||||
R_cmp2 = R_s4 // R_cmp2 = 20 = s4
|
||||
};
|
||||
|
||||
|
||||
|
||||
}; // namespace android
|
||||
|
||||
#endif //ANDROID_MIPSASSEMBLER_H
|
|
@ -110,7 +110,11 @@ void GGLAssembler::extract(integer_t& d, int s, int h, int l, int bits)
|
|||
{
|
||||
const int maskLen = h-l;
|
||||
|
||||
#ifdef __mips__
|
||||
assert(maskLen<=11);
|
||||
#else
|
||||
assert(maskLen<=8);
|
||||
#endif
|
||||
assert(h);
|
||||
|
||||
#if __ARM_ARCH__ >= 7
|
||||
|
|
|
@ -0,0 +1,590 @@
|
|||
/* $NetBSD: db_disasm.c,v 1.19 2007/02/28 04:21:53 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Ralph Campbell.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)kadb.c 8.1 (Berkeley) 6/10/93
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include "mips_opcode.h"
|
||||
|
||||
|
||||
// #include <sys/systm.h>
|
||||
// #include <sys/param.h>
|
||||
|
||||
// #include <machine/reg.h>
|
||||
// #include <machine/cpu.h>
|
||||
/*#include <machine/param.h>*/
|
||||
// #include <machine/db_machdep.h>
|
||||
|
||||
// #include <ddb/db_interface.h>
|
||||
// #include <ddb/db_output.h>
|
||||
// #include <ddb/db_extern.h>
|
||||
// #include <ddb/db_sym.h>
|
||||
|
||||
|
||||
static char *sprintf_buffer;
|
||||
static int sprintf_buf_len;
|
||||
|
||||
|
||||
typedef uint32_t db_addr_t;
|
||||
static void db_printf(const char* fmt, ...);
|
||||
|
||||
static const char * const op_name[64] = {
|
||||
/* 0 */ "spec", "bcond","j ", "jal", "beq", "bne", "blez", "bgtz",
|
||||
/* 8 */ "addi", "addiu","slti", "sltiu","andi", "ori", "xori", "lui",
|
||||
/*16 */ "cop0", "cop1", "cop2", "cop3", "beql", "bnel", "blezl","bgtzl",
|
||||
/*24 */ "daddi","daddiu","ldl", "ldr", "op34", "op35", "op36", "op37",
|
||||
/*32 */ "lb ", "lh ", "lwl", "lw ", "lbu", "lhu", "lwr", "lwu",
|
||||
/*40 */ "sb ", "sh ", "swl", "sw ", "sdl", "sdr", "swr", "cache",
|
||||
/*48 */ "ll ", "lwc1", "lwc2", "lwc3", "lld", "ldc1", "ldc2", "ld ",
|
||||
/*56 */ "sc ", "swc1", "swc2", "swc3", "scd", "sdc1", "sdc2", "sd "
|
||||
};
|
||||
|
||||
static const char * const spec_name[64] = {
|
||||
/* 0 */ "sll", "spec01","srl", "sra", "sllv", "spec05","srlv","srav",
|
||||
/* 8 */ "jr", "jalr", "movz","movn","syscall","break","spec16","sync",
|
||||
/*16 */ "mfhi", "mthi", "mflo", "mtlo", "dsllv","spec25","dsrlv","dsrav",
|
||||
/*24 */ "mult", "multu","div", "divu", "dmult","dmultu","ddiv","ddivu",
|
||||
/*32 */ "add", "addu", "sub", "subu", "and", "or ", "xor", "nor",
|
||||
/*40 */ "spec50","spec51","slt","sltu", "dadd","daddu","dsub","dsubu",
|
||||
/*48 */ "tge","tgeu","tlt","tltu","teq","spec65","tne","spec67",
|
||||
/*56 */ "dsll","spec71","dsrl","dsra","dsll32","spec75","dsrl32","dsra32"
|
||||
};
|
||||
|
||||
static const char * const spec2_name[64] = { /* QED RM4650, R5000, etc. */
|
||||
/* 0x00 */ "madd", "maddu", "mul", "spec3", "msub", "msubu", "rsrv6", "rsrv7",
|
||||
/* 0x08 */ "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv",
|
||||
/* 0x10 */ "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv",
|
||||
/* 0x18 */ "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv",
|
||||
/* 0x20 */ "clz", "clo", "rsrv", "rsrv", "dclz", "dclo", "rsrv", "rsrv",
|
||||
/* 0x28 */ "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv",
|
||||
/* 0x30 */ "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv", "rsrv",
|
||||
/* 0x38 */ "rsrv", "rsrv", "rsrv", "resv", "rsrv", "rsrv", "rsrv", "sdbbp"
|
||||
};
|
||||
|
||||
static const char * const bcond_name[32] = {
|
||||
/* 0 */ "bltz", "bgez", "bltzl", "bgezl", "?", "?", "?", "?",
|
||||
/* 8 */ "tgei", "tgeiu", "tlti", "tltiu", "teqi", "?", "tnei", "?",
|
||||
/*16 */ "bltzal", "bgezal", "bltzall", "bgezall", "?", "?", "?", "?",
|
||||
/*24 */ "?", "?", "?", "?", "?", "?", "?", "?",
|
||||
};
|
||||
|
||||
static const char * const cop1_name[64] = {
|
||||
/* 0 */ "fadd", "fsub", "fmpy", "fdiv", "fsqrt","fabs", "fmov", "fneg",
|
||||
/* 8 */ "fop08","fop09","fop0a","fop0b","fop0c","fop0d","fop0e","fop0f",
|
||||
/*16 */ "fop10","fop11","fop12","fop13","fop14","fop15","fop16","fop17",
|
||||
/*24 */ "fop18","fop19","fop1a","fop1b","fop1c","fop1d","fop1e","fop1f",
|
||||
/*32 */ "fcvts","fcvtd","fcvte","fop23","fcvtw","fop25","fop26","fop27",
|
||||
/*40 */ "fop28","fop29","fop2a","fop2b","fop2c","fop2d","fop2e","fop2f",
|
||||
/*48 */ "fcmp.f","fcmp.un","fcmp.eq","fcmp.ueq","fcmp.olt","fcmp.ult",
|
||||
"fcmp.ole","fcmp.ule",
|
||||
/*56 */ "fcmp.sf","fcmp.ngle","fcmp.seq","fcmp.ngl","fcmp.lt","fcmp.nge",
|
||||
"fcmp.le","fcmp.ngt"
|
||||
};
|
||||
|
||||
static const char * const fmt_name[16] = {
|
||||
"s", "d", "e", "fmt3",
|
||||
"w", "fmt5", "fmt6", "fmt7",
|
||||
"fmt8", "fmt9", "fmta", "fmtb",
|
||||
"fmtc", "fmtd", "fmte", "fmtf"
|
||||
};
|
||||
|
||||
#if defined(__mips_n32) || defined(__mips_n64)
|
||||
static char * const reg_name[32] = {
|
||||
"zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
|
||||
"a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
|
||||
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
|
||||
"t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
|
||||
};
|
||||
#else
|
||||
|
||||
static char * alt_arm_reg_name[32] = { // hacked names for comparison with ARM code
|
||||
"zero", "at", "r0", "r1", "r2", "r3", "r4", "r5",
|
||||
"r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13",
|
||||
"r14", "r15", "at2", "cmp", "s4", "s5", "s6", "s7",
|
||||
"t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
|
||||
};
|
||||
|
||||
static char * mips_reg_name[32] = {
|
||||
"zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
|
||||
"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
|
||||
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
|
||||
"t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
|
||||
};
|
||||
|
||||
static char ** reg_name = &mips_reg_name[0];
|
||||
|
||||
#endif /* __mips_n32 || __mips_n64 */
|
||||
|
||||
static const char * const c0_opname[64] = {
|
||||
"c0op00","tlbr", "tlbwi", "c0op03","c0op04","c0op05","tlbwr", "c0op07",
|
||||
"tlbp", "c0op11","c0op12","c0op13","c0op14","c0op15","c0op16","c0op17",
|
||||
"rfe", "c0op21","c0op22","c0op23","c0op24","c0op25","c0op26","c0op27",
|
||||
"eret", "c0op31","c0op32","c0op33","c0op34","c0op35","c0op36","c0op37",
|
||||
"c0op40","c0op41","c0op42","c0op43","c0op44","c0op45","c0op46","c0op47",
|
||||
"c0op50","c0op51","c0op52","c0op53","c0op54","c0op55","c0op56","c0op57",
|
||||
"c0op60","c0op61","c0op62","c0op63","c0op64","c0op65","c0op66","c0op67",
|
||||
"c0op70","c0op71","c0op72","c0op73","c0op74","c0op75","c0op77","c0op77",
|
||||
};
|
||||
|
||||
static const char * const c0_reg[32] = {
|
||||
"index", "random", "tlblo0", "tlblo1",
|
||||
"context", "pagemask", "wired", "cp0r7",
|
||||
"badvaddr", "count", "tlbhi", "compare",
|
||||
"status", "cause", "epc", "prid",
|
||||
"config", "lladdr", "watchlo", "watchhi",
|
||||
"xcontext", "cp0r21", "cp0r22", "debug",
|
||||
"depc", "perfcnt", "ecc", "cacheerr",
|
||||
"taglo", "taghi", "errepc", "desave"
|
||||
};
|
||||
|
||||
static void print_addr(db_addr_t);
|
||||
db_addr_t mips_disassem(db_addr_t loc, char *di_buffer, int alt_dis_format);
|
||||
|
||||
|
||||
/*
|
||||
* Disassemble instruction 'insn' nominally at 'loc'.
|
||||
* 'loc' may in fact contain a breakpoint instruction.
|
||||
*/
|
||||
static db_addr_t
|
||||
db_disasm_insn(int insn, db_addr_t loc, bool altfmt)
|
||||
{
|
||||
bool bdslot = false;
|
||||
InstFmt i;
|
||||
|
||||
i.word = insn;
|
||||
|
||||
switch (i.JType.op) {
|
||||
case OP_SPECIAL:
|
||||
if (i.word == 0) {
|
||||
db_printf("nop");
|
||||
break;
|
||||
}
|
||||
if (i.word == 0x0080) {
|
||||
db_printf("NIY");
|
||||
break;
|
||||
}
|
||||
if (i.word == 0x00c0) {
|
||||
db_printf("NOT IMPL");
|
||||
break;
|
||||
}
|
||||
/* Special cases --------------------------------------------------
|
||||
* "addu" is a "move" only in 32-bit mode. What's the correct
|
||||
* answer - never decode addu/daddu as "move"?
|
||||
*/
|
||||
if ( (i.RType.func == OP_ADDU && i.RType.rt == 0) ||
|
||||
(i.RType.func == OP_OR && i.RType.rt == 0) ) {
|
||||
db_printf("move\t%s,%s",
|
||||
reg_name[i.RType.rd],
|
||||
reg_name[i.RType.rs]);
|
||||
break;
|
||||
}
|
||||
// mips32r2, rotr & rotrv
|
||||
if (i.RType.func == OP_SRL && (i.RType.rs & 1) == 1) {
|
||||
db_printf("rotr\t%s,%s,%d", reg_name[i.RType.rd],
|
||||
reg_name[i.RType.rt], i.RType.shamt);
|
||||
break;
|
||||
}
|
||||
if (i.RType.func == OP_SRLV && (i.RType.shamt & 1) == 1) {
|
||||
db_printf("rotrv\t%s,%s,%s", reg_name[i.RType.rd],
|
||||
reg_name[i.RType.rt], reg_name[i.RType.rs]);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
db_printf("%s", spec_name[i.RType.func]);
|
||||
switch (i.RType.func) {
|
||||
case OP_SLL:
|
||||
case OP_SRL:
|
||||
case OP_SRA:
|
||||
case OP_DSLL:
|
||||
|
||||
case OP_DSRL:
|
||||
case OP_DSRA:
|
||||
case OP_DSLL32:
|
||||
case OP_DSRL32:
|
||||
case OP_DSRA32:
|
||||
db_printf("\t%s,%s,%d",
|
||||
reg_name[i.RType.rd],
|
||||
reg_name[i.RType.rt],
|
||||
i.RType.shamt);
|
||||
break;
|
||||
|
||||
case OP_SLLV:
|
||||
case OP_SRLV:
|
||||
case OP_SRAV:
|
||||
case OP_DSLLV:
|
||||
case OP_DSRLV:
|
||||
case OP_DSRAV:
|
||||
db_printf("\t%s,%s,%s",
|
||||
reg_name[i.RType.rd],
|
||||
reg_name[i.RType.rt],
|
||||
reg_name[i.RType.rs]);
|
||||
break;
|
||||
|
||||
case OP_MFHI:
|
||||
case OP_MFLO:
|
||||
db_printf("\t%s", reg_name[i.RType.rd]);
|
||||
break;
|
||||
|
||||
case OP_JR:
|
||||
case OP_JALR:
|
||||
db_printf("\t%s", reg_name[i.RType.rs]);
|
||||
bdslot = true;
|
||||
break;
|
||||
case OP_MTLO:
|
||||
case OP_MTHI:
|
||||
db_printf("\t%s", reg_name[i.RType.rs]);
|
||||
break;
|
||||
|
||||
case OP_MULT:
|
||||
case OP_MULTU:
|
||||
case OP_DMULT:
|
||||
case OP_DMULTU:
|
||||
case OP_DIV:
|
||||
case OP_DIVU:
|
||||
case OP_DDIV:
|
||||
case OP_DDIVU:
|
||||
db_printf("\t%s,%s",
|
||||
reg_name[i.RType.rs],
|
||||
reg_name[i.RType.rt]);
|
||||
break;
|
||||
|
||||
|
||||
case OP_SYSCALL:
|
||||
case OP_SYNC:
|
||||
break;
|
||||
|
||||
case OP_BREAK:
|
||||
db_printf("\t%d", (i.RType.rs << 5) | i.RType.rt);
|
||||
break;
|
||||
|
||||
default:
|
||||
db_printf("\t%s,%s,%s",
|
||||
reg_name[i.RType.rd],
|
||||
reg_name[i.RType.rs],
|
||||
reg_name[i.RType.rt]);
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_SPECIAL2:
|
||||
if (i.RType.func == OP_MUL)
|
||||
db_printf("%s\t%s,%s,%s",
|
||||
spec2_name[i.RType.func & 0x3f],
|
||||
reg_name[i.RType.rd],
|
||||
reg_name[i.RType.rs],
|
||||
reg_name[i.RType.rt]);
|
||||
else
|
||||
db_printf("%s\t%s,%s",
|
||||
spec2_name[i.RType.func & 0x3f],
|
||||
reg_name[i.RType.rs],
|
||||
reg_name[i.RType.rt]);
|
||||
|
||||
break;
|
||||
|
||||
case OP_SPECIAL3:
|
||||
if (i.RType.func == OP_EXT)
|
||||
db_printf("ext\t%s,%s,%d,%d",
|
||||
reg_name[i.RType.rt],
|
||||
reg_name[i.RType.rs],
|
||||
i.RType.rd+1,
|
||||
i.RType.shamt);
|
||||
else if (i.RType.func == OP_INS)
|
||||
db_printf("ins\t%s,%s,%d,%d",
|
||||
reg_name[i.RType.rt],
|
||||
reg_name[i.RType.rs],
|
||||
i.RType.rd+1,
|
||||
i.RType.shamt);
|
||||
else if (i.RType.func == OP_BSHFL && i.RType.shamt == OP_WSBH)
|
||||
db_printf("wsbh\t%s,%s",
|
||||
reg_name[i.RType.rd],
|
||||
reg_name[i.RType.rt]);
|
||||
else if (i.RType.func == OP_BSHFL && i.RType.shamt == OP_SEB)
|
||||
db_printf("seb\t%s,%s",
|
||||
reg_name[i.RType.rd],
|
||||
reg_name[i.RType.rt]);
|
||||
else if (i.RType.func == OP_BSHFL && i.RType.shamt == OP_SEH)
|
||||
db_printf("seh\t%s,%s",
|
||||
reg_name[i.RType.rd],
|
||||
reg_name[i.RType.rt]);
|
||||
else
|
||||
db_printf("Unknown");
|
||||
break;
|
||||
|
||||
case OP_BCOND:
|
||||
db_printf("%s\t%s,", bcond_name[i.IType.rt],
|
||||
reg_name[i.IType.rs]);
|
||||
goto pr_displ;
|
||||
|
||||
case OP_BLEZ:
|
||||
case OP_BLEZL:
|
||||
case OP_BGTZ:
|
||||
case OP_BGTZL:
|
||||
db_printf("%s\t%s,", op_name[i.IType.op],
|
||||
reg_name[i.IType.rs]);
|
||||
goto pr_displ;
|
||||
|
||||
case OP_BEQ:
|
||||
case OP_BEQL:
|
||||
if (i.IType.rs == 0 && i.IType.rt == 0) {
|
||||
db_printf("b \t");
|
||||
goto pr_displ;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case OP_BNE:
|
||||
case OP_BNEL:
|
||||
db_printf("%s\t%s,%s,", op_name[i.IType.op],
|
||||
reg_name[i.IType.rs],
|
||||
reg_name[i.IType.rt]);
|
||||
pr_displ:
|
||||
print_addr(loc + 4 + ((short)i.IType.imm << 2));
|
||||
bdslot = true;
|
||||
break;
|
||||
|
||||
case OP_COP0:
|
||||
switch (i.RType.rs) {
|
||||
case OP_BCx:
|
||||
case OP_BCy:
|
||||
|
||||
db_printf("bc0%c\t",
|
||||
"ft"[i.RType.rt & COPz_BC_TF_MASK]);
|
||||
goto pr_displ;
|
||||
|
||||
case OP_MT:
|
||||
db_printf("mtc0\t%s,%s",
|
||||
reg_name[i.RType.rt],
|
||||
c0_reg[i.RType.rd]);
|
||||
break;
|
||||
|
||||
case OP_DMT:
|
||||
db_printf("dmtc0\t%s,%s",
|
||||
reg_name[i.RType.rt],
|
||||
c0_reg[i.RType.rd]);
|
||||
break;
|
||||
|
||||
case OP_MF:
|
||||
db_printf("mfc0\t%s,%s",
|
||||
reg_name[i.RType.rt],
|
||||
c0_reg[i.RType.rd]);
|
||||
break;
|
||||
|
||||
case OP_DMF:
|
||||
db_printf("dmfc0\t%s,%s",
|
||||
reg_name[i.RType.rt],
|
||||
c0_reg[i.RType.rd]);
|
||||
break;
|
||||
|
||||
default:
|
||||
db_printf("%s", c0_opname[i.FRType.func]);
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_COP1:
|
||||
switch (i.RType.rs) {
|
||||
case OP_BCx:
|
||||
case OP_BCy:
|
||||
db_printf("bc1%c\t",
|
||||
"ft"[i.RType.rt & COPz_BC_TF_MASK]);
|
||||
goto pr_displ;
|
||||
|
||||
case OP_MT:
|
||||
db_printf("mtc1\t%s,f%d",
|
||||
reg_name[i.RType.rt],
|
||||
i.RType.rd);
|
||||
break;
|
||||
|
||||
case OP_MF:
|
||||
db_printf("mfc1\t%s,f%d",
|
||||
reg_name[i.RType.rt],
|
||||
i.RType.rd);
|
||||
break;
|
||||
|
||||
case OP_CT:
|
||||
db_printf("ctc1\t%s,f%d",
|
||||
reg_name[i.RType.rt],
|
||||
i.RType.rd);
|
||||
break;
|
||||
|
||||
case OP_CF:
|
||||
db_printf("cfc1\t%s,f%d",
|
||||
reg_name[i.RType.rt],
|
||||
i.RType.rd);
|
||||
break;
|
||||
|
||||
default:
|
||||
db_printf("%s.%s\tf%d,f%d,f%d",
|
||||
cop1_name[i.FRType.func],
|
||||
fmt_name[i.FRType.fmt],
|
||||
i.FRType.fd, i.FRType.fs, i.FRType.ft);
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_J:
|
||||
case OP_JAL:
|
||||
db_printf("%s\t", op_name[i.JType.op]);
|
||||
print_addr((loc & 0xF0000000) | (i.JType.target << 2));
|
||||
bdslot = true;
|
||||
break;
|
||||
|
||||
case OP_LWC1:
|
||||
case OP_SWC1:
|
||||
db_printf("%s\tf%d,", op_name[i.IType.op],
|
||||
i.IType.rt);
|
||||
goto loadstore;
|
||||
|
||||
case OP_LB:
|
||||
case OP_LH:
|
||||
case OP_LW:
|
||||
case OP_LD:
|
||||
case OP_LBU:
|
||||
case OP_LHU:
|
||||
case OP_LWU:
|
||||
case OP_SB:
|
||||
case OP_SH:
|
||||
case OP_SW:
|
||||
case OP_SD:
|
||||
db_printf("%s\t%s,", op_name[i.IType.op],
|
||||
reg_name[i.IType.rt]);
|
||||
loadstore:
|
||||
db_printf("%d(%s)", (short)i.IType.imm,
|
||||
reg_name[i.IType.rs]);
|
||||
break;
|
||||
|
||||
case OP_ORI:
|
||||
case OP_XORI:
|
||||
if (i.IType.rs == 0) {
|
||||
db_printf("li\t%s,0x%x",
|
||||
reg_name[i.IType.rt],
|
||||
i.IType.imm);
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case OP_ANDI:
|
||||
db_printf("%s\t%s,%s,0x%x", op_name[i.IType.op],
|
||||
reg_name[i.IType.rt],
|
||||
reg_name[i.IType.rs],
|
||||
i.IType.imm);
|
||||
break;
|
||||
|
||||
case OP_LUI:
|
||||
db_printf("%s\t%s,0x%x", op_name[i.IType.op],
|
||||
reg_name[i.IType.rt],
|
||||
i.IType.imm);
|
||||
break;
|
||||
|
||||
case OP_CACHE:
|
||||
db_printf("%s\t0x%x,0x%x(%s)",
|
||||
op_name[i.IType.op],
|
||||
i.IType.rt,
|
||||
i.IType.imm,
|
||||
reg_name[i.IType.rs]);
|
||||
break;
|
||||
|
||||
case OP_ADDI:
|
||||
case OP_DADDI:
|
||||
case OP_ADDIU:
|
||||
case OP_DADDIU:
|
||||
if (i.IType.rs == 0) {
|
||||
db_printf("li\t%s,%d",
|
||||
reg_name[i.IType.rt],
|
||||
(short)i.IType.imm);
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
db_printf("%s\t%s,%s,%d", op_name[i.IType.op],
|
||||
reg_name[i.IType.rt],
|
||||
reg_name[i.IType.rs],
|
||||
(short)i.IType.imm);
|
||||
}
|
||||
// db_printf("\n");
|
||||
// if (bdslot) {
|
||||
// db_printf(" bd: ");
|
||||
// mips_disassem(loc+4);
|
||||
// return (loc + 8);
|
||||
// }
|
||||
return (loc + 4);
|
||||
}
|
||||
|
||||
static void
|
||||
print_addr(db_addr_t loc)
|
||||
{
|
||||
db_printf("0x%08x", loc);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void db_printf(const char* fmt, ...)
|
||||
{
|
||||
int cnt;
|
||||
va_list argp;
|
||||
va_start(argp, fmt);
|
||||
if (sprintf_buffer) {
|
||||
cnt = vsnprintf(sprintf_buffer, sprintf_buf_len, fmt, argp);
|
||||
sprintf_buffer += cnt;
|
||||
sprintf_buf_len -= cnt;
|
||||
} else {
|
||||
vprintf(fmt, argp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Disassemble instruction at 'loc'.
|
||||
* Return address of start of next instruction.
|
||||
* Since this function is used by 'examine' and by 'step'
|
||||
* "next instruction" does NOT mean the next instruction to
|
||||
* be executed but the 'linear' next instruction.
|
||||
*/
|
||||
db_addr_t
|
||||
mips_disassem(db_addr_t loc, char *di_buffer, int alt_dis_format)
|
||||
{
|
||||
u_int32_t instr;
|
||||
|
||||
if (alt_dis_format) { // use ARM register names for disassembly
|
||||
reg_name = &alt_arm_reg_name[0];
|
||||
}
|
||||
|
||||
sprintf_buffer = di_buffer; // quick 'n' dirty printf() vs sprintf()
|
||||
sprintf_buf_len = 39; // should be passed in
|
||||
|
||||
instr = *(u_int32_t *)loc;
|
||||
return (db_disasm_insn(instr, loc, false));
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/* $NetBSD: db_disasm.c,v 1.19 2007/02/28 04:21:53 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Ralph Campbell.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)kadb.c 8.1 (Berkeley) 6/10/93
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef ANDROID_MIPS_DISASSEM_H
|
||||
#define ANDROID_MIPS_DISASSEM_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
// could add an interface like this, but I have not
|
||||
// typedef struct {
|
||||
// u_int (*di_readword)(u_int);
|
||||
// void (*di_printaddr)(u_int);
|
||||
// void (*di_printf)(const char *, ...);
|
||||
// } disasm_interface_t;
|
||||
|
||||
/* Prototypes for callable functions */
|
||||
|
||||
// u_int disasm(const disasm_interface_t *, u_int, int);
|
||||
|
||||
void mips_disassem(uint32_t *location, char *di_buffer, int alt_fmt);
|
||||
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !ANDROID_MIPS_DISASSEM_H */
|
|
@ -0,0 +1,316 @@
|
|||
/* $NetBSD: mips_opcode.h,v 1.12 2005/12/11 12:18:09 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Ralph Campbell.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)mips_opcode.h 8.1 (Berkeley) 6/10/93
|
||||
*/
|
||||
|
||||
/*
|
||||
* Define the instruction formats and opcode values for the
|
||||
* MIPS instruction set.
|
||||
*/
|
||||
|
||||
#include <endian.h>
|
||||
|
||||
/*
|
||||
* Define the instruction formats.
|
||||
*/
|
||||
typedef union {
|
||||
unsigned word;
|
||||
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
struct {
|
||||
unsigned imm: 16;
|
||||
unsigned rt: 5;
|
||||
unsigned rs: 5;
|
||||
unsigned op: 6;
|
||||
} IType;
|
||||
|
||||
struct {
|
||||
unsigned target: 26;
|
||||
unsigned op: 6;
|
||||
} JType;
|
||||
|
||||
struct {
|
||||
unsigned func: 6;
|
||||
unsigned shamt: 5;
|
||||
unsigned rd: 5;
|
||||
unsigned rt: 5;
|
||||
unsigned rs: 5;
|
||||
unsigned op: 6;
|
||||
} RType;
|
||||
|
||||
struct {
|
||||
unsigned func: 6;
|
||||
unsigned fd: 5;
|
||||
unsigned fs: 5;
|
||||
unsigned ft: 5;
|
||||
unsigned fmt: 4;
|
||||
unsigned : 1; /* always '1' */
|
||||
unsigned op: 6; /* always '0x11' */
|
||||
} FRType;
|
||||
#endif
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
struct {
|
||||
unsigned op: 6;
|
||||
unsigned rs: 5;
|
||||
unsigned rt: 5;
|
||||
unsigned imm: 16;
|
||||
} IType;
|
||||
|
||||
struct {
|
||||
unsigned op: 6;
|
||||
unsigned target: 26;
|
||||
} JType;
|
||||
|
||||
struct {
|
||||
unsigned op: 6;
|
||||
unsigned rs: 5;
|
||||
unsigned rt: 5;
|
||||
unsigned rd: 5;
|
||||
unsigned shamt: 5;
|
||||
unsigned func: 6;
|
||||
} RType;
|
||||
|
||||
struct {
|
||||
unsigned op: 6; /* always '0x11' */
|
||||
unsigned : 1; /* always '1' */
|
||||
unsigned fmt: 4;
|
||||
unsigned ft: 5;
|
||||
unsigned fs: 5;
|
||||
unsigned fd: 5;
|
||||
unsigned func: 6;
|
||||
} FRType;
|
||||
#endif
|
||||
} InstFmt;
|
||||
|
||||
/*
|
||||
* Values for the 'op' field.
|
||||
*/
|
||||
#define OP_SPECIAL 000
|
||||
#define OP_BCOND 001
|
||||
#define OP_J 002
|
||||
#define OP_JAL 003
|
||||
#define OP_BEQ 004
|
||||
#define OP_BNE 005
|
||||
#define OP_BLEZ 006
|
||||
#define OP_BGTZ 007
|
||||
|
||||
#define OP_ADDI 010
|
||||
#define OP_ADDIU 011
|
||||
#define OP_SLTI 012
|
||||
#define OP_SLTIU 013
|
||||
#define OP_ANDI 014
|
||||
#define OP_ORI 015
|
||||
#define OP_XORI 016
|
||||
#define OP_LUI 017
|
||||
|
||||
#define OP_COP0 020
|
||||
#define OP_COP1 021
|
||||
#define OP_COP2 022
|
||||
#define OP_COP3 023
|
||||
#define OP_BEQL 024 /* MIPS-II, for r4000 port */
|
||||
#define OP_BNEL 025 /* MIPS-II, for r4000 port */
|
||||
#define OP_BLEZL 026 /* MIPS-II, for r4000 port */
|
||||
#define OP_BGTZL 027 /* MIPS-II, for r4000 port */
|
||||
|
||||
#define OP_DADDI 030 /* MIPS-II, for r4000 port */
|
||||
#define OP_DADDIU 031 /* MIPS-II, for r4000 port */
|
||||
#define OP_LDL 032 /* MIPS-II, for r4000 port */
|
||||
#define OP_LDR 033 /* MIPS-II, for r4000 port */
|
||||
|
||||
#define OP_SPECIAL2 034 /* QED opcodes */
|
||||
#define OP_SPECIAL3 037 /* mips32r2 opcodes */
|
||||
|
||||
#define OP_LB 040
|
||||
#define OP_LH 041
|
||||
#define OP_LWL 042
|
||||
#define OP_LW 043
|
||||
#define OP_LBU 044
|
||||
#define OP_LHU 045
|
||||
#define OP_LWR 046
|
||||
#define OP_LHU 045
|
||||
#define OP_LWR 046
|
||||
#define OP_LWU 047 /* MIPS-II, for r4000 port */
|
||||
|
||||
#define OP_SB 050
|
||||
#define OP_SH 051
|
||||
#define OP_SWL 052
|
||||
#define OP_SW 053
|
||||
#define OP_SDL 054 /* MIPS-II, for r4000 port */
|
||||
#define OP_SDR 055 /* MIPS-II, for r4000 port */
|
||||
#define OP_SWR 056
|
||||
#define OP_CACHE 057 /* MIPS-II, for r4000 port */
|
||||
|
||||
#define OP_LL 060
|
||||
#define OP_LWC0 OP_LL /* backwards source compatibility */
|
||||
#define OP_LWC1 061
|
||||
#define OP_LWC2 062
|
||||
#define OP_LWC3 063
|
||||
#define OP_LLD 064 /* MIPS-II, for r4000 port */
|
||||
#define OP_LDC1 065
|
||||
#define OP_LD 067 /* MIPS-II, for r4000 port */
|
||||
|
||||
#define OP_SC 070
|
||||
#define OP_SWC0 OP_SC /* backwards source compatibility */
|
||||
#define OP_SWC1 071
|
||||
#define OP_SWC2 072
|
||||
#define OP_SWC3 073
|
||||
#define OP_SCD 074 /* MIPS-II, for r4000 port */
|
||||
#define OP_SDC1 075
|
||||
#define OP_SD 077 /* MIPS-II, for r4000 port */
|
||||
|
||||
/*
|
||||
* Values for the 'func' field when 'op' == OP_SPECIAL.
|
||||
*/
|
||||
#define OP_SLL 000
|
||||
#define OP_SRL 002
|
||||
#define OP_SRA 003
|
||||
#define OP_SLLV 004
|
||||
#define OP_SRLV 006
|
||||
#define OP_SRAV 007
|
||||
|
||||
#define OP_JR 010
|
||||
#define OP_JALR 011
|
||||
#define OP_SYSCALL 014
|
||||
#define OP_BREAK 015
|
||||
#define OP_SYNC 017 /* MIPS-II, for r4000 port */
|
||||
|
||||
#define OP_MFHI 020
|
||||
#define OP_MTHI 021
|
||||
#define OP_MFLO 022
|
||||
#define OP_MTLO 023
|
||||
#define OP_DSLLV 024 /* MIPS-II, for r4000 port */
|
||||
#define OP_DSRLV 026 /* MIPS-II, for r4000 port */
|
||||
#define OP_DSRAV 027 /* MIPS-II, for r4000 port */
|
||||
|
||||
#define OP_MULT 030
|
||||
#define OP_MULTU 031
|
||||
#define OP_DIV 032
|
||||
#define OP_DIVU 033
|
||||
#define OP_DMULT 034 /* MIPS-II, for r4000 port */
|
||||
#define OP_DMULTU 035 /* MIPS-II, for r4000 port */
|
||||
#define OP_DDIV 036 /* MIPS-II, for r4000 port */
|
||||
#define OP_DDIVU 037 /* MIPS-II, for r4000 port */
|
||||
|
||||
#define OP_ADD 040
|
||||
#define OP_ADDU 041
|
||||
#define OP_SUB 042
|
||||
#define OP_SUBU 043
|
||||
#define OP_AND 044
|
||||
#define OP_OR 045
|
||||
#define OP_XOR 046
|
||||
#define OP_NOR 047
|
||||
|
||||
#define OP_SLT 052
|
||||
#define OP_SLTU 053
|
||||
#define OP_DADD 054 /* MIPS-II, for r4000 port */
|
||||
#define OP_DADDU 055 /* MIPS-II, for r4000 port */
|
||||
#define OP_DSUB 056 /* MIPS-II, for r4000 port */
|
||||
#define OP_DSUBU 057 /* MIPS-II, for r4000 port */
|
||||
|
||||
#define OP_TGE 060 /* MIPS-II, for r4000 port */
|
||||
#define OP_TGEU 061 /* MIPS-II, for r4000 port */
|
||||
#define OP_TLT 062 /* MIPS-II, for r4000 port */
|
||||
#define OP_TLTU 063 /* MIPS-II, for r4000 port */
|
||||
#define OP_TEQ 064 /* MIPS-II, for r4000 port */
|
||||
#define OP_TNE 066 /* MIPS-II, for r4000 port */
|
||||
|
||||
#define OP_DSLL 070 /* MIPS-II, for r4000 port */
|
||||
#define OP_DSRL 072 /* MIPS-II, for r4000 port */
|
||||
#define OP_DSRA 073 /* MIPS-II, for r4000 port */
|
||||
#define OP_DSLL32 074 /* MIPS-II, for r4000 port */
|
||||
#define OP_DSRL32 076 /* MIPS-II, for r4000 port */
|
||||
#define OP_DSRA32 077 /* MIPS-II, for r4000 port */
|
||||
|
||||
/*
|
||||
* Values for the 'func' field when 'op' == OP_SPECIAL2.
|
||||
*/
|
||||
#define OP_MAD 000 /* QED */
|
||||
#define OP_MADU 001 /* QED */
|
||||
#define OP_MUL 002 /* QED */
|
||||
|
||||
/*
|
||||
* Values for the 'func' field when 'op' == OP_SPECIAL3.
|
||||
*/
|
||||
#define OP_EXT 000
|
||||
#define OP_INS 004
|
||||
#define OP_BSHFL 040
|
||||
|
||||
/*
|
||||
* Values for the 'shamt' field when OP_SPECIAL3 && func OP_BSHFL.
|
||||
*/
|
||||
#define OP_WSBH 002
|
||||
#define OP_SEB 020
|
||||
#define OP_SEH 030
|
||||
|
||||
/*
|
||||
* Values for the 'func' field when 'op' == OP_BCOND.
|
||||
*/
|
||||
#define OP_BLTZ 000
|
||||
#define OP_BGEZ 001
|
||||
#define OP_BLTZL 002 /* MIPS-II, for r4000 port */
|
||||
#define OP_BGEZL 003 /* MIPS-II, for r4000 port */
|
||||
|
||||
#define OP_TGEI 010 /* MIPS-II, for r4000 port */
|
||||
#define OP_TGEIU 011 /* MIPS-II, for r4000 port */
|
||||
#define OP_TLTI 012 /* MIPS-II, for r4000 port */
|
||||
#define OP_TLTIU 013 /* MIPS-II, for r4000 port */
|
||||
#define OP_TEQI 014 /* MIPS-II, for r4000 port */
|
||||
#define OP_TNEI 016 /* MIPS-II, for r4000 port */
|
||||
|
||||
#define OP_BLTZAL 020 /* MIPS-II, for r4000 port */
|
||||
#define OP_BGEZAL 021
|
||||
#define OP_BLTZALL 022
|
||||
#define OP_BGEZALL 023
|
||||
|
||||
/*
|
||||
* Values for the 'rs' field when 'op' == OP_COPz.
|
||||
*/
|
||||
#define OP_MF 000
|
||||
#define OP_DMF 001 /* MIPS-II, for r4000 port */
|
||||
#define OP_MT 004
|
||||
#define OP_DMT 005 /* MIPS-II, for r4000 port */
|
||||
#define OP_BCx 010
|
||||
#define OP_BCy 014
|
||||
#define OP_CF 002
|
||||
#define OP_CT 006
|
||||
|
||||
/*
|
||||
* Values for the 'rt' field when 'op' == OP_COPz.
|
||||
*/
|
||||
#define COPz_BC_TF_MASK 0x01
|
||||
#define COPz_BC_TRUE 0x01
|
||||
#define COPz_BC_FALSE 0x00
|
||||
#define COPz_BCL_TF_MASK 0x02 /* MIPS-II, for r4000 port */
|
||||
#define COPz_BCL_TRUE 0x02 /* MIPS-II, for r4000 port */
|
||||
#define COPz_BCL_FALSE 0x00 /* MIPS-II, for r4000 port */
|
|
@ -464,6 +464,9 @@ void GGLAssembler::build_textures( fragment_parts_t& parts,
|
|||
CONTEXT_LOAD(t.reg, generated_vars.texture[i].spill[1]);
|
||||
}
|
||||
|
||||
if (registerFile().status() & RegisterFile::OUT_OF_REGISTERS)
|
||||
return;
|
||||
|
||||
comment("compute repeat/clamp");
|
||||
int u = scratches.obtain();
|
||||
int v = scratches.obtain();
|
||||
|
@ -472,6 +475,9 @@ void GGLAssembler::build_textures( fragment_parts_t& parts,
|
|||
int U = 0;
|
||||
int V = 0;
|
||||
|
||||
if (registerFile().status() & RegisterFile::OUT_OF_REGISTERS)
|
||||
return;
|
||||
|
||||
CONTEXT_LOAD(width, generated_vars.texture[i].width);
|
||||
CONTEXT_LOAD(height, generated_vars.texture[i].height);
|
||||
|
||||
|
@ -510,6 +516,9 @@ void GGLAssembler::build_textures( fragment_parts_t& parts,
|
|||
U = scratches.obtain();
|
||||
V = scratches.obtain();
|
||||
|
||||
if (registerFile().status() & RegisterFile::OUT_OF_REGISTERS)
|
||||
return;
|
||||
|
||||
// sample the texel center
|
||||
SUB(AL, 0, u, u, imm(1<<(FRAC_BITS-1)));
|
||||
SUB(AL, 0, v, v, imm(1<<(FRAC_BITS-1)));
|
||||
|
@ -593,6 +602,10 @@ void GGLAssembler::build_textures( fragment_parts_t& parts,
|
|||
comment("iterate s,t");
|
||||
int dsdx = scratches.obtain();
|
||||
int dtdx = scratches.obtain();
|
||||
|
||||
if (registerFile().status() & RegisterFile::OUT_OF_REGISTERS)
|
||||
return;
|
||||
|
||||
CONTEXT_LOAD(dsdx, generated_vars.texture[i].dsdx);
|
||||
CONTEXT_LOAD(dtdx, generated_vars.texture[i].dtdx);
|
||||
ADD(AL, 0, s.reg, s.reg, dsdx);
|
||||
|
@ -611,6 +624,10 @@ void GGLAssembler::build_textures( fragment_parts_t& parts,
|
|||
texel.setTo(regs.obtain(), &tmu.format);
|
||||
txPtr.setTo(texel.reg, tmu.bits);
|
||||
int stride = scratches.obtain();
|
||||
|
||||
if (registerFile().status() & RegisterFile::OUT_OF_REGISTERS)
|
||||
return;
|
||||
|
||||
CONTEXT_LOAD(stride, generated_vars.texture[i].stride);
|
||||
CONTEXT_LOAD(txPtr.reg, generated_vars.texture[i].data);
|
||||
SMLABB(AL, u, v, stride, u); // u+v*stride
|
||||
|
@ -1078,6 +1095,7 @@ void GGLAssembler::build_texture_environment(
|
|||
|
||||
Scratch scratches(registerFile());
|
||||
pixel_t texel(parts.texel[i]);
|
||||
|
||||
if (multiTexture &&
|
||||
tmu.swrap == GGL_NEEDS_WRAP_11 &&
|
||||
tmu.twrap == GGL_NEEDS_WRAP_11)
|
||||
|
|
|
@ -32,6 +32,9 @@
|
|||
#include "codeflinger/CodeCache.h"
|
||||
#include "codeflinger/GGLAssembler.h"
|
||||
#include "codeflinger/ARMAssembler.h"
|
||||
#if defined(__mips__)
|
||||
#include "codeflinger/MIPSAssembler.h"
|
||||
#endif
|
||||
//#include "codeflinger/ARMAssemblerOptimizer.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -49,7 +52,7 @@
|
|||
# define ANDROID_CODEGEN ANDROID_CODEGEN_GENERATED
|
||||
#endif
|
||||
|
||||
#if defined(__arm__)
|
||||
#if defined(__arm__) || defined(__mips__)
|
||||
# define ANDROID_ARM_CODEGEN 1
|
||||
#else
|
||||
# define ANDROID_ARM_CODEGEN 0
|
||||
|
@ -63,7 +66,11 @@
|
|||
*/
|
||||
#define DEBUG_NEEDS 0
|
||||
|
||||
#ifdef __mips__
|
||||
#define ASSEMBLY_SCRATCH_SIZE 4096
|
||||
#else
|
||||
#define ASSEMBLY_SCRATCH_SIZE 2048
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
namespace android {
|
||||
|
@ -266,7 +273,12 @@ static const needs_filter_t fill16noblend = {
|
|||
// ----------------------------------------------------------------------------
|
||||
|
||||
#if ANDROID_ARM_CODEGEN
|
||||
|
||||
#if defined(__mips__)
|
||||
static CodeCache gCodeCache(32 * 1024);
|
||||
#else
|
||||
static CodeCache gCodeCache(12 * 1024);
|
||||
#endif
|
||||
|
||||
class ScanlineAssembly : public Assembly {
|
||||
AssemblyKey<needs_t> mKey;
|
||||
|
@ -375,9 +387,14 @@ static void pick_scanline(context_t* c)
|
|||
sp<ScanlineAssembly> a = new ScanlineAssembly(c->state.needs,
|
||||
ASSEMBLY_SCRATCH_SIZE);
|
||||
// initialize our assembler
|
||||
#if defined(__arm__)
|
||||
GGLAssembler assembler( new ARMAssembler(a) );
|
||||
//GGLAssembler assembler(
|
||||
// new ARMAssemblerOptimizer(new ARMAssembler(a)) );
|
||||
#endif
|
||||
#if defined(__mips__)
|
||||
GGLAssembler assembler( new ArmToMipsAssembler(a) );
|
||||
#endif
|
||||
// generate the scanline code for the given needs
|
||||
int err = assembler.scanline(c->state.needs, c);
|
||||
if (ggl_likely(!err)) {
|
||||
|
|
|
@ -9,14 +9,19 @@
|
|||
#include "codeflinger/CodeCache.h"
|
||||
#include "codeflinger/GGLAssembler.h"
|
||||
#include "codeflinger/ARMAssembler.h"
|
||||
#include "codeflinger/MIPSAssembler.h"
|
||||
|
||||
#if defined(__arm__)
|
||||
#if defined(__arm__) || defined(__mips__)
|
||||
# define ANDROID_ARM_CODEGEN 1
|
||||
#else
|
||||
# define ANDROID_ARM_CODEGEN 0
|
||||
#endif
|
||||
|
||||
#if defined (__mips__)
|
||||
#define ASSEMBLY_SCRATCH_SIZE 4096
|
||||
#else
|
||||
#define ASSEMBLY_SCRATCH_SIZE 2048
|
||||
#endif
|
||||
|
||||
using namespace android;
|
||||
|
||||
|
@ -39,14 +44,22 @@ static void ggl_test_codegen(uint32_t n, uint32_t p, uint32_t t0, uint32_t t1)
|
|||
needs.t[0] = t0;
|
||||
needs.t[1] = t1;
|
||||
sp<ScanlineAssembly> a(new ScanlineAssembly(needs, ASSEMBLY_SCRATCH_SIZE));
|
||||
|
||||
#if defined(__arm__)
|
||||
GGLAssembler assembler( new ARMAssembler(a) );
|
||||
#endif
|
||||
|
||||
#if defined(__mips__)
|
||||
GGLAssembler assembler( new ArmToMipsAssembler(a) );
|
||||
#endif
|
||||
|
||||
int err = assembler.scanline(needs, (context_t*)c);
|
||||
if (err != 0) {
|
||||
printf("error %08x (%s)\n", err, strerror(-err));
|
||||
}
|
||||
gglUninit(c);
|
||||
#else
|
||||
printf("This test runs only on ARM\n");
|
||||
printf("This test runs only on ARM or MIPS\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue