| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482 |
- /*
- Copyright (c) 2019, tevador <tevador@gmail.com>
- All rights reserved.
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * 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.
- * Neither the name of the copyright holder 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
- */
- #include "bytecode_machine.hpp"
- #include "reciprocal.h"
- namespace randomx {
- const int_reg_t BytecodeMachine::zero = 0;
- #define INSTR_CASE(x) case InstructionType::x: \
- exe_ ## x(ibc, pc, scratchpad, config); \
- break;
- void BytecodeMachine::executeInstruction(RANDOMX_EXE_ARGS) {
- switch (ibc.type)
- {
- INSTR_CASE(IADD_RS)
- INSTR_CASE(IADD_M)
- INSTR_CASE(ISUB_R)
- INSTR_CASE(ISUB_M)
- INSTR_CASE(IMUL_R)
- INSTR_CASE(IMUL_M)
- INSTR_CASE(IMULH_R)
- INSTR_CASE(IMULH_M)
- INSTR_CASE(ISMULH_R)
- INSTR_CASE(ISMULH_M)
- INSTR_CASE(INEG_R)
- INSTR_CASE(IXOR_R)
- INSTR_CASE(IXOR_M)
- INSTR_CASE(IROR_R)
- INSTR_CASE(IROL_R)
- INSTR_CASE(ISWAP_R)
- INSTR_CASE(FSWAP_R)
- INSTR_CASE(FADD_R)
- INSTR_CASE(FADD_M)
- INSTR_CASE(FSUB_R)
- INSTR_CASE(FSUB_M)
- INSTR_CASE(FSCAL_R)
- INSTR_CASE(FMUL_R)
- INSTR_CASE(FDIV_M)
- INSTR_CASE(FSQRT_R)
- INSTR_CASE(CBRANCH)
- INSTR_CASE(CFROUND)
- INSTR_CASE(ISTORE)
- case InstructionType::NOP:
- break;
- case InstructionType::IMUL_RCP: //executed as IMUL_R
- default:
- UNREACHABLE;
- }
- }
- void BytecodeMachine::compileInstruction(RANDOMX_GEN_ARGS) {
- int opcode = instr.opcode;
- if (opcode < ceil_IADD_RS) {
- auto dst = instr.dst % RegistersCount;
- auto src = instr.src % RegistersCount;
- ibc.type = InstructionType::IADD_RS;
- ibc.idst = &nreg->r[dst];
- if (dst != RegisterNeedsDisplacement) {
- ibc.isrc = &nreg->r[src];
- ibc.shift = instr.getModShift();
- ibc.imm = 0;
- }
- else {
- ibc.isrc = &nreg->r[src];
- ibc.shift = instr.getModShift();
- ibc.imm = signExtend2sCompl(instr.getImm32());
- }
- registerUsage[dst] = i;
- return;
- }
- if (opcode < ceil_IADD_M) {
- auto dst = instr.dst % RegistersCount;
- auto src = instr.src % RegistersCount;
- ibc.type = InstructionType::IADD_M;
- ibc.idst = &nreg->r[dst];
- ibc.imm = signExtend2sCompl(instr.getImm32());
- if (src != dst) {
- ibc.isrc = &nreg->r[src];
- ibc.memMask = (instr.getModMem() ? ScratchpadL1Mask : ScratchpadL2Mask);
- }
- else {
- ibc.isrc = &zero;
- ibc.memMask = ScratchpadL3Mask;
- }
- registerUsage[dst] = i;
- return;
- }
- if (opcode < ceil_ISUB_R) {
- auto dst = instr.dst % RegistersCount;
- auto src = instr.src % RegistersCount;
- ibc.type = InstructionType::ISUB_R;
- ibc.idst = &nreg->r[dst];
- if (src != dst) {
- ibc.isrc = &nreg->r[src];
- }
- else {
- ibc.imm = signExtend2sCompl(instr.getImm32());
- ibc.isrc = &ibc.imm;
- }
- registerUsage[dst] = i;
- return;
- }
- if (opcode < ceil_ISUB_M) {
- auto dst = instr.dst % RegistersCount;
- auto src = instr.src % RegistersCount;
- ibc.type = InstructionType::ISUB_M;
- ibc.idst = &nreg->r[dst];
- ibc.imm = signExtend2sCompl(instr.getImm32());
- if (src != dst) {
- ibc.isrc = &nreg->r[src];
- ibc.memMask = (instr.getModMem() ? ScratchpadL1Mask : ScratchpadL2Mask);
- }
- else {
- ibc.isrc = &zero;
- ibc.memMask = ScratchpadL3Mask;
- }
- registerUsage[dst] = i;
- return;
- }
- if (opcode < ceil_IMUL_R) {
- auto dst = instr.dst % RegistersCount;
- auto src = instr.src % RegistersCount;
- ibc.type = InstructionType::IMUL_R;
- ibc.idst = &nreg->r[dst];
- if (src != dst) {
- ibc.isrc = &nreg->r[src];
- }
- else {
- ibc.imm = signExtend2sCompl(instr.getImm32());
- ibc.isrc = &ibc.imm;
- }
- registerUsage[dst] = i;
- return;
- }
- if (opcode < ceil_IMUL_M) {
- auto dst = instr.dst % RegistersCount;
- auto src = instr.src % RegistersCount;
- ibc.type = InstructionType::IMUL_M;
- ibc.idst = &nreg->r[dst];
- ibc.imm = signExtend2sCompl(instr.getImm32());
- if (src != dst) {
- ibc.isrc = &nreg->r[src];
- ibc.memMask = (instr.getModMem() ? ScratchpadL1Mask : ScratchpadL2Mask);
- }
- else {
- ibc.isrc = &zero;
- ibc.memMask = ScratchpadL3Mask;
- }
- registerUsage[dst] = i;
- return;
- }
- if (opcode < ceil_IMULH_R) {
- auto dst = instr.dst % RegistersCount;
- auto src = instr.src % RegistersCount;
- ibc.type = InstructionType::IMULH_R;
- ibc.idst = &nreg->r[dst];
- ibc.isrc = &nreg->r[src];
- registerUsage[dst] = i;
- return;
- }
- if (opcode < ceil_IMULH_M) {
- auto dst = instr.dst % RegistersCount;
- auto src = instr.src % RegistersCount;
- ibc.type = InstructionType::IMULH_M;
- ibc.idst = &nreg->r[dst];
- ibc.imm = signExtend2sCompl(instr.getImm32());
- if (src != dst) {
- ibc.isrc = &nreg->r[src];
- ibc.memMask = (instr.getModMem() ? ScratchpadL1Mask : ScratchpadL2Mask);
- }
- else {
- ibc.isrc = &zero;
- ibc.memMask = ScratchpadL3Mask;
- }
- registerUsage[dst] = i;
- return;
- }
- if (opcode < ceil_ISMULH_R) {
- auto dst = instr.dst % RegistersCount;
- auto src = instr.src % RegistersCount;
- ibc.type = InstructionType::ISMULH_R;
- ibc.idst = &nreg->r[dst];
- ibc.isrc = &nreg->r[src];
- registerUsage[dst] = i;
- return;
- }
- if (opcode < ceil_ISMULH_M) {
- auto dst = instr.dst % RegistersCount;
- auto src = instr.src % RegistersCount;
- ibc.type = InstructionType::ISMULH_M;
- ibc.idst = &nreg->r[dst];
- ibc.imm = signExtend2sCompl(instr.getImm32());
- if (src != dst) {
- ibc.isrc = &nreg->r[src];
- ibc.memMask = (instr.getModMem() ? ScratchpadL1Mask : ScratchpadL2Mask);
- }
- else {
- ibc.isrc = &zero;
- ibc.memMask = ScratchpadL3Mask;
- }
- registerUsage[dst] = i;
- return;
- }
- if (opcode < ceil_IMUL_RCP) {
- uint64_t divisor = instr.getImm32();
- if (!isZeroOrPowerOf2(divisor)) {
- auto dst = instr.dst % RegistersCount;
- ibc.type = InstructionType::IMUL_R;
- ibc.idst = &nreg->r[dst];
- ibc.imm = randomx_reciprocal(divisor);
- ibc.isrc = &ibc.imm;
- registerUsage[dst] = i;
- }
- else {
- ibc.type = InstructionType::NOP;
- }
- return;
- }
- if (opcode < ceil_INEG_R) {
- auto dst = instr.dst % RegistersCount;
- ibc.type = InstructionType::INEG_R;
- ibc.idst = &nreg->r[dst];
- registerUsage[dst] = i;
- return;
- }
- if (opcode < ceil_IXOR_R) {
- auto dst = instr.dst % RegistersCount;
- auto src = instr.src % RegistersCount;
- ibc.type = InstructionType::IXOR_R;
- ibc.idst = &nreg->r[dst];
- if (src != dst) {
- ibc.isrc = &nreg->r[src];
- }
- else {
- ibc.imm = signExtend2sCompl(instr.getImm32());
- ibc.isrc = &ibc.imm;
- }
- registerUsage[dst] = i;
- return;
- }
- if (opcode < ceil_IXOR_M) {
- auto dst = instr.dst % RegistersCount;
- auto src = instr.src % RegistersCount;
- ibc.type = InstructionType::IXOR_M;
- ibc.idst = &nreg->r[dst];
- ibc.imm = signExtend2sCompl(instr.getImm32());
- if (src != dst) {
- ibc.isrc = &nreg->r[src];
- ibc.memMask = (instr.getModMem() ? ScratchpadL1Mask : ScratchpadL2Mask);
- }
- else {
- ibc.isrc = &zero;
- ibc.memMask = ScratchpadL3Mask;
- }
- registerUsage[dst] = i;
- return;
- }
- if (opcode < ceil_IROR_R) {
- auto dst = instr.dst % RegistersCount;
- auto src = instr.src % RegistersCount;
- ibc.type = InstructionType::IROR_R;
- ibc.idst = &nreg->r[dst];
- if (src != dst) {
- ibc.isrc = &nreg->r[src];
- }
- else {
- ibc.imm = instr.getImm32();
- ibc.isrc = &ibc.imm;
- }
- registerUsage[dst] = i;
- return;
- }
- if (opcode < ceil_IROL_R) {
- auto dst = instr.dst % RegistersCount;
- auto src = instr.src % RegistersCount;
- ibc.type = InstructionType::IROL_R;
- ibc.idst = &nreg->r[dst];
- if (src != dst) {
- ibc.isrc = &nreg->r[src];
- }
- else {
- ibc.imm = instr.getImm32();
- ibc.isrc = &ibc.imm;
- }
- registerUsage[dst] = i;
- return;
- }
- if (opcode < ceil_ISWAP_R) {
- auto dst = instr.dst % RegistersCount;
- auto src = instr.src % RegistersCount;
- if (src != dst) {
- ibc.idst = &nreg->r[dst];
- ibc.isrc = &nreg->r[src];
- ibc.type = InstructionType::ISWAP_R;
- registerUsage[dst] = i;
- registerUsage[src] = i;
- }
- else {
- ibc.type = InstructionType::NOP;
- }
- return;
- }
- if (opcode < ceil_FSWAP_R) {
- auto dst = instr.dst % RegistersCount;
- ibc.type = InstructionType::FSWAP_R;
- if (dst < RegisterCountFlt)
- ibc.fdst = &nreg->f[dst];
- else
- ibc.fdst = &nreg->e[dst - RegisterCountFlt];
- return;
- }
- if (opcode < ceil_FADD_R) {
- auto dst = instr.dst % RegisterCountFlt;
- auto src = instr.src % RegisterCountFlt;
- ibc.type = InstructionType::FADD_R;
- ibc.fdst = &nreg->f[dst];
- ibc.fsrc = &nreg->a[src];
- return;
- }
- if (opcode < ceil_FADD_M) {
- auto dst = instr.dst % RegisterCountFlt;
- auto src = instr.src % RegistersCount;
- ibc.type = InstructionType::FADD_M;
- ibc.fdst = &nreg->f[dst];
- ibc.isrc = &nreg->r[src];
- ibc.memMask = (instr.getModMem() ? ScratchpadL1Mask : ScratchpadL2Mask);
- ibc.imm = signExtend2sCompl(instr.getImm32());
- return;
- }
- if (opcode < ceil_FSUB_R) {
- auto dst = instr.dst % RegisterCountFlt;
- auto src = instr.src % RegisterCountFlt;
- ibc.type = InstructionType::FSUB_R;
- ibc.fdst = &nreg->f[dst];
- ibc.fsrc = &nreg->a[src];
- return;
- }
- if (opcode < ceil_FSUB_M) {
- auto dst = instr.dst % RegisterCountFlt;
- auto src = instr.src % RegistersCount;
- ibc.type = InstructionType::FSUB_M;
- ibc.fdst = &nreg->f[dst];
- ibc.isrc = &nreg->r[src];
- ibc.memMask = (instr.getModMem() ? ScratchpadL1Mask : ScratchpadL2Mask);
- ibc.imm = signExtend2sCompl(instr.getImm32());
- return;
- }
- if (opcode < ceil_FSCAL_R) {
- auto dst = instr.dst % RegisterCountFlt;
- ibc.fdst = &nreg->f[dst];
- ibc.type = InstructionType::FSCAL_R;
- return;
- }
- if (opcode < ceil_FMUL_R) {
- auto dst = instr.dst % RegisterCountFlt;
- auto src = instr.src % RegisterCountFlt;
- ibc.type = InstructionType::FMUL_R;
- ibc.fdst = &nreg->e[dst];
- ibc.fsrc = &nreg->a[src];
- return;
- }
- if (opcode < ceil_FDIV_M) {
- auto dst = instr.dst % RegisterCountFlt;
- auto src = instr.src % RegistersCount;
- ibc.type = InstructionType::FDIV_M;
- ibc.fdst = &nreg->e[dst];
- ibc.isrc = &nreg->r[src];
- ibc.memMask = (instr.getModMem() ? ScratchpadL1Mask : ScratchpadL2Mask);
- ibc.imm = signExtend2sCompl(instr.getImm32());
- return;
- }
- if (opcode < ceil_FSQRT_R) {
- auto dst = instr.dst % RegisterCountFlt;
- ibc.type = InstructionType::FSQRT_R;
- ibc.fdst = &nreg->e[dst];
- return;
- }
- if (opcode < ceil_CBRANCH) {
- ibc.type = InstructionType::CBRANCH;
- //jump condition
- int creg = instr.dst % RegistersCount;
- ibc.idst = &nreg->r[creg];
- ibc.target = registerUsage[creg];
- int shift = instr.getModCond() + ConditionOffset;
- ibc.imm = signExtend2sCompl(instr.getImm32()) | (1ULL << shift);
- if (ConditionOffset > 0 || shift > 0) //clear the bit below the condition mask - this limits the number of successive jumps to 2
- ibc.imm &= ~(1ULL << (shift - 1));
- ibc.memMask = ConditionMask << shift;
- //mark all registers as used
- for (unsigned j = 0; j < RegistersCount; ++j) {
- registerUsage[j] = i;
- }
- return;
- }
- if (opcode < ceil_CFROUND) {
- auto src = instr.src % RegistersCount;
- ibc.isrc = &nreg->r[src];
- ibc.type = InstructionType::CFROUND;
- ibc.imm = instr.getImm32() & 63;
- return;
- }
- if (opcode < ceil_ISTORE) {
- auto dst = instr.dst % RegistersCount;
- auto src = instr.src % RegistersCount;
- ibc.type = InstructionType::ISTORE;
- ibc.idst = &nreg->r[dst];
- ibc.isrc = &nreg->r[src];
- ibc.imm = signExtend2sCompl(instr.getImm32());
- if (instr.getModCond() < StoreL3Condition)
- ibc.memMask = (instr.getModMem() ? ScratchpadL1Mask : ScratchpadL2Mask);
- else
- ibc.memMask = ScratchpadL3Mask;
- return;
- }
- if (opcode < ceil_NOP) {
- ibc.type = InstructionType::NOP;
- return;
- }
- UNREACHABLE;
- }
- }
|