tevador / RandomX

Proof of work algorithm based on random code execution
BSD 3-Clause "New" or "Revised" License
1.41k stars 307 forks source link

Where do a lot of these magic numbers and instructions for x86 come from? #302

Closed Redhawk18 closed 3 weeks ago

Redhawk18 commented 3 weeks ago

Hey, I started studying this projected and wanted to ask for links the to references used for the instructions for the jit compiler and the superscalerhashing.

I was using this resource to look for instructions

For example I can't find info on this code was based on

    enum class SuperscalarInstructionType {       //uOPs (decode)   execution ports         latency       code size
        ISUB_R = 0,                               //1               p015                    1               3 (sub)
        IXOR_R = 1,                               //1               p015                    1               3 (xor)
        IADD_RS = 2,                              //1               p01                     1               4 (lea)
        IMUL_R = 3,                               //1               p1                      3               4 (imul)
        IROR_C = 4,                               //1               p05                     1               4 (ror)
        IADD_C7 = 5,                              //1               p015                    1               7 (add)
        IXOR_C7 = 6,                              //1               p015                    1               7 (xor)
        IADD_C8 = 7,                              //1+0             p015                    1               7+1 (add+nop)
        IXOR_C8 = 8,                              //1+0             p015                    1               7+1 (xor+nop)
        IADD_C9 = 9,                              //1+0             p015                    1               7+2 (add+nop)
        IXOR_C9 = 10,                             //1+0             p015                    1               7+2 (xor+nop)
        IMULH_R = 11,                             //1+2+1           0+(p1,p5)+0             3               3+3+3 (mov+mul+mov)
        ISMULH_R = 12,                            //1+2+1           0+(p1,p5)+0             3               3+3+3 (mov+imul+mov)
        IMUL_RCP = 13,                            //1+1             p015+p1                 4              10+4   (mov+imul)

        COUNT = 14,
        INVALID = -1
    };

Or where these specialized add instructions come from

    class JitCompilerX86 {
    public:

    private:
...

        void h_IADD_RS(Instruction&, int);
        void h_IADD_M(Instruction&, int);

I can't find any add instructions with RS or M but I'm also pretty new to this space.

And where do these constants come from?

    static const uint8_t REX_ADD_RR[] = { 0x4d, 0x03 };
    static const uint8_t REX_ADD_RM[] = { 0x4c, 0x03 };
    static const uint8_t REX_SUB_RR[] = { 0x4d, 0x2b };
    static const uint8_t REX_SUB_RM[] = { 0x4c, 0x2b };
    static const uint8_t REX_MOV_RR[] = { 0x41, 0x8b };
    static const uint8_t REX_MOV_RR64[] = { 0x49, 0x8b };
    static const uint8_t REX_MOV_R64R[] = { 0x4c, 0x8b };
    static const uint8_t REX_IMUL_RR[] = { 0x4d, 0x0f, 0xaf };
        ...
SChernykh commented 3 weeks ago

RandomX runs its own virtual machine which was designed from ground up, and it uses its own instructions, so there's no point to search for IADD_RS on the Internet. These instructions, however, directly translate (with a few exceptions) to native x86-64 or aarch64 instructions.

Redhawk18 commented 3 weeks ago

RandomX runs its own virtual machine which was designed from ground up, and it uses its own instructions, so there's no point to search for IADD_RS on the Internet. These instructions, however, directly translate (with a few exceptions) to native x86-64 or aarch64 instructions.

So all the instructions are what is defined in superscalar? Also can you explain the COUNT and invalid instructions, I'm unsure if you could replace invalid with an optional. Also could you explain where the hex values come from in the x86 jit compiler?

SChernykh commented 3 weeks ago

The hex values come from the x86 instruction encodings. As for RandomX instructions, you can read https://github.com/tevador/RandomX/blob/master/doc/specs.md and https://github.com/tevador/RandomX/blob/master/doc/design.md