| 122 | } |
| 123 | |
| 124 | void CPU::call(U32 big, U32 selector, U32 offset, U32 oldEip) { |
| 125 | if (this->flags & VM) { |
| 126 | U32 esp = THIS_ESP; // // don't set ESP until we are done with memory Writes / push so that we are reentrant |
| 127 | if (big) { |
| 128 | esp = push32_r(esp, this->seg[CS].value); |
| 129 | esp = push32_r(esp, oldEip); |
| 130 | this->eip.u32 = offset; |
| 131 | } else { |
| 132 | esp = push16_r(esp, this->seg[CS].value); |
| 133 | esp = push16_r(esp, oldEip & 0xFFFF); |
| 134 | this->eip.u32 = offset & 0xffff; |
| 135 | } |
| 136 | THIS_ESP = esp; |
| 137 | this->setIsBig(0); |
| 138 | this->setSeg(CS, selector << 4, selector); |
| 139 | } else { |
| 140 | //U32 rpl=selector & 3; |
| 141 | U32 index = selector >> 3; |
| 142 | |
| 143 | if (CPU_CHECK_COND(this, (selector & 0xfffc)==0, "CALL:CS selector zero", EXCEPTION_GP,0)) |
| 144 | return; |
| 145 | |
| 146 | if (index>=LDT_ENTRIES) { |
| 147 | CPU_CHECK_COND(this, 0, "CALL:CS beyond limits", EXCEPTION_GP,selector & 0xfffc); |
| 148 | return; |
| 149 | } |
| 150 | struct user_desc* ldt = this->thread->getLDT(index); |
| 151 | |
| 152 | if (this->thread->isLdtEmpty(ldt)) { |
| 153 | prepareException(EXCEPTION_NP,selector & 0xfffc); |
| 154 | return; |
| 155 | } |
| 156 | |
| 157 | U32 esp = THIS_ESP; |
| 158 | // commit point |
| 159 | if (big) { |
| 160 | esp = push32_r(esp, this->seg[CS].value); |
| 161 | esp = push32_r(esp, oldEip); |
| 162 | this->eip.u32=offset; |
| 163 | } else { |
| 164 | esp = push16_r(esp, this->seg[CS].value); |
| 165 | esp = push16_r(esp, oldEip); |
| 166 | this->eip.u32=offset & 0xffff; |
| 167 | } |
| 168 | THIS_ESP = esp; // don't set ESP until we are done with Memory Writes / CPU_Push so that we are reentrant |
| 169 | this->setIsBig(ldt->seg_32bit); |
| 170 | this->setSeg(CS, ldt->base_addr, (selector & 0xfffc) | this->cpl); |
| 171 | } |
| 172 | } |
| 173 | |
| 174 | void CPU::jmp(U32 big, U32 selector, U32 offset, U32 oldEip) { |
| 175 | if (this->flags & VM) { |
no test coverage detected