alu2(this, GEN_OPCODE_JMPI, GenRegister::ip(), GenRegister::ip(), src);
}
- void Gen75Encoder::patchJMPI(uint32_t insnID, int32_t jumpDistance) {
+ void Gen75Encoder::patchJMPI(uint32_t insnID, int32_t jip, int32_t uip) {
GenNativeInstruction &insn = *(GenNativeInstruction *)&this->store[insnID];
GBE_ASSERT(insnID < this->store.size());
GBE_ASSERT(insn.header.opcode == GEN_OPCODE_JMPI ||
if( insn.header.opcode == GEN_OPCODE_WHILE ){
// if this WHILE instruction jump back to an ELSE instruction,
// need add distance to go to the next instruction.
- GenNativeInstruction & insn_else = *(GenNativeInstruction *)&this->store[insnID+jumpDistance];
+ GenNativeInstruction & insn_else = *(GenNativeInstruction *)&this->store[insnID+jip];
if(insn_else.header.opcode == GEN_OPCODE_ELSE){
- jumpDistance += 2;
+ jip += 2;
}
}
- if (insn.header.opcode != GEN_OPCODE_JMPI)
- this->setSrc1(&insn, GenRegister::immd(jumpDistance));
- else {
+ if (insn.header.opcode == GEN_OPCODE_JMPI) {
//jumpDistance'unit is Qword, and the HSW's JMPI offset of jmpi is in byte, so multi 8
- jumpDistance = (jumpDistance - 2) * 8;
- this->setSrc1(&insn, GenRegister::immd(jumpDistance));
+ jip = (jip - 2) * 8;
}
+ this->setSrc1(&insn, GenRegister::immd((jip & 0xffff) | uip<<16));
return;
}
} /* End of the name space. */
/*! Jump indexed instruction */
virtual void JMPI(GenRegister src, bool longjmp = false);
/*! Patch JMPI/BRC/BRD (located at index insnID) with the given jump distance */
- virtual void patchJMPI(uint32_t insnID, int32_t jumpDistance);
+ virtual void patchJMPI(uint32_t insnID, int32_t jip, int32_t uip);
/*! Get double/long exec width */
virtual int getDoubleExecWidth(void) { return GEN75_DOUBLE_EXEC_WIDTH; }
virtual void MOV_DF(GenRegister dest, GenRegister src0, GenRegister tmp = GenRegister::null());
alu2(this, GEN_OPCODE_JMPI, GenRegister::ip(), GenRegister::ip(), src);
}
- void Gen8Encoder::patchJMPI(uint32_t insnID, int32_t jumpDistance) {
+ void Gen8Encoder::patchJMPI(uint32_t insnID, int32_t jip, int32_t uip) {
GenNativeInstruction &insn = *(GenNativeInstruction *)&this->store[insnID];
GBE_ASSERT(insnID < this->store.size());
GBE_ASSERT(insn.header.opcode == GEN_OPCODE_JMPI ||
insn.header.opcode == GEN_OPCODE_ENDIF ||
insn.header.opcode == GEN_OPCODE_IF ||
insn.header.opcode == GEN_OPCODE_BRC ||
+ insn.header.opcode == GEN_OPCODE_WHILE ||
insn.header.opcode == GEN_OPCODE_ELSE);
+ if( insn.header.opcode == GEN_OPCODE_WHILE ) {
+ // if this WHILE instruction jump back to an ELSE instruction,
+ // need add distance to go to the next instruction.
+ GenNativeInstruction & insn_else = *(GenNativeInstruction *)&this->store[insnID+jip];
+ if(insn_else.header.opcode == GEN_OPCODE_ELSE) {
+ jip += 2;
+ }
+ }
+
+ if(insn.header.opcode == GEN_OPCODE_ELSE)
+ uip = jip;
+
if (insn.header.opcode == GEN_OPCODE_IF) {
- this->setSrc1(&insn, GenRegister::immd(jumpDistance));
+ Gen8NativeInstruction *gen8_insn = &insn.gen8_insn;
+ this->setSrc0(&insn, GenRegister::immud(0));
+ gen8_insn->bits2.gen8_branch.uip = uip*8;
+ gen8_insn->bits3.gen8_branch.jip = jip*8;
return;
}
else if (insn.header.opcode == GEN_OPCODE_JMPI) {
//jumpDistance'unit is Qword, and the HSW's offset of jmpi is in byte, so multi 8
- jumpDistance = (jumpDistance - 2) * 8;
+ jip = (jip - 2);
}
- this->setSrc1(&insn, GenRegister::immd(jumpDistance));
+ this->setSrc1(&insn, GenRegister::immd(jip*8));
}
void Gen8Encoder::setDst(GenNativeInstruction *insn, GenRegister dest) {
/*! Jump indexed instruction */
virtual void JMPI(GenRegister src, bool longjmp = false);
/*! Patch JMPI/BRC/BRD (located at index insnID) with the given jump distance */
- virtual void patchJMPI(uint32_t insnID, int32_t jumpDistance);
+ virtual void patchJMPI(uint32_t insnID, int32_t jip, int32_t uip);
/*! Get double/long exec width */
virtual int getDoubleExecWidth(void) { return GEN8_DOUBLE_EXEC_WIDTH; }
virtual void MOV_DF(GenRegister dest, GenRegister src0, GenRegister tmp = GenRegister::null());
const LabelIndex label = pair.first;
const int32_t insnID = pair.second;
const int32_t targetID = labelPos.find(label)->second;
- p->patchJMPI(insnID, (targetID - insnID));
+ p->patchJMPI(insnID, (targetID - insnID), 0);
}
for (auto pair : branchPos3) {
const LabelPair labelPair = pair.first;
errCode = OUT_OF_RANGE_IF_ENDIF;
return false;
}
- p->patchJMPI(insnID, ((uip - insnID) << 16) | (0x0000ffff & (jip - insnID)));
+ p->patchJMPI(insnID, jip - insnID, uip - insnID);
}
return true;
}
p->SHL(high, low, tmp);
p->MOV(low, GenRegister::immud(0));
- p->patchJMPI(jip1, (p->n_instruction() - jip1) );
+ p->patchJMPI(jip1, (p->n_instruction() - jip1), 0);
p->curr.predicate = GEN_PREDICATE_NONE;
p->CMP(GEN_CONDITIONAL_LE, exp, GenRegister::immud(31)); //update dst where high != 0
p->curr.predicate = GEN_PREDICATE_NORMAL;
p->CMP(GEN_CONDITIONAL_EQ, high, GenRegister::immud(0x80000000));
p->CMP(GEN_CONDITIONAL_EQ, low, GenRegister::immud(0x0));
p->AND(dst_ud, dst_ud, GenRegister::immud(0xfffffffe));
- p->patchJMPI(jip0, (p->n_instruction() - jip0));
+ p->patchJMPI(jip0, (p->n_instruction() - jip0), 0);
p->pop();
p->curr.noMask = 1;
jip0 = p->n_instruction();
p->JMPI(zero);
- p->patchJMPI(jip0, distance);
+ p->patchJMPI(jip0, distance, 0);
p->pop();
// end of loop
}
ALU2_BRA(BRD)
ALU2_BRA(BRC)
- void GenEncoder::patchJMPI(uint32_t insnID, int32_t jumpDistance) {
+ void GenEncoder::patchJMPI(uint32_t insnID, int32_t jip, int32_t uip) {
GenNativeInstruction &insn = *(GenNativeInstruction *)&this->store[insnID];
GBE_ASSERT(insnID < this->store.size());
GBE_ASSERT(insn.header.opcode == GEN_OPCODE_JMPI ||
if( insn.header.opcode == GEN_OPCODE_WHILE ){
// if this WHILE instruction jump back to an ELSE instruction,
// need add distance to go to the next instruction.
- GenNativeInstruction & insn_else = *(GenNativeInstruction *)&this->store[insnID+jumpDistance];
+ GenNativeInstruction & insn_else = *(GenNativeInstruction *)&this->store[insnID+jip];
if(insn_else.header.opcode == GEN_OPCODE_ELSE){
- jumpDistance += 2;
+ jip += 2;
}
}
- if (insn.header.opcode != GEN_OPCODE_JMPI || (jumpDistance > -32769 && jumpDistance < 32768)) {
- if (insn.header.opcode == GEN_OPCODE_IF) {
- this->setSrc1(&insn, GenRegister::immd(jumpDistance));
- return;
- }
- else if (insn.header.opcode == GEN_OPCODE_JMPI){
- jumpDistance = jumpDistance - 2;
- }
- else if(insn.header.opcode == GEN_OPCODE_ENDIF)
- jumpDistance += 2;
-
- this->setSrc1(&insn, GenRegister::immd(jumpDistance));
+ if (insn.header.opcode != GEN_OPCODE_JMPI || (jip > -32769 && jip < 32768)) {
+ if (insn.header.opcode == GEN_OPCODE_IF) {
+ this->setSrc1(&insn, GenRegister::immd((jip & 0xffff) | uip<<16));
+ return;
+ } else if (insn.header.opcode == GEN_OPCODE_JMPI) {
+ jip = jip - 2;
+ } else if(insn.header.opcode == GEN_OPCODE_ENDIF)
+ jip += 2;
+ this->setSrc1(&insn, GenRegister::immd((jip & 0xffff) | uip<<16));
} else if ( insn.header.predicate_control == GEN_PREDICATE_NONE ) {
// For the conditional jump distance out of S15 range, we need to use an
// inverted jmp followed by a add ip, ip, distance to implement.
insn.header.opcode = GEN_OPCODE_ADD;
this->setDst(&insn, GenRegister::ip());
this->setSrc0(&insn, GenRegister::ip());
- this->setSrc1(&insn, GenRegister::immd(jumpDistance * 8));
+ this->setSrc1(&insn, GenRegister::immd(jip * 8));
} else {
GenNativeInstruction &insn2 = *(GenNativeInstruction *)&this->store[insnID+2];
insn.header.predicate_inverse ^= 1;
insn2.header.opcode = GEN_OPCODE_ADD;
this->setDst(&insn2, GenRegister::ip());
this->setSrc0(&insn2, GenRegister::ip());
- this->setSrc1(&insn2, GenRegister::immd((jumpDistance - 2) * 8));
+ this->setSrc1(&insn2, GenRegister::immd((jip - 2) * 8));
}
}
void MATH(GenRegister dst, uint32_t function, GenRegister src);
/*! Patch JMPI/BRC/BRD (located at index insnID) with the given jump distance */
- virtual void patchJMPI(uint32_t insnID, int32_t jumpDistance);
+ virtual void patchJMPI(uint32_t insnID, int32_t jip, int32_t uip);
////////////////////////////////////////////////////////////////////////
// Helper functions to encode