m3back/src/Codex86.i3


 Copyright (C) 1993, Digital Equipment Corporation           
 All rights reserved.                                        
 See the file COPYRIGHT for a full description.              
                                                             
 Last modified on Tue Oct 11 14:32:39 PDT 1994 by isard      
      modified on Fri Nov 19 09:30:31 PST 1993 by kalsow     
      modified on Mon Apr 13 09:55:12 PDT 1992 by muller     

INTERFACE Codex86;

IMPORT M3CG, M3ObjFile, TFloat, TIntN;
FROM M3CG IMPORT MType, Label, ByteOffset, Type;
FROM M3CG_Ops IMPORT ErrorHandler;
IMPORT M3x86Rep, Wrx86;
FROM M3x86Rep IMPORT Operand, NRegs, MVar, x86Var, x86Proc, Regno;

TYPE T <: Public;
TYPE Public = OBJECT
        wr         : Wrx86.T := NIL;
        reg        : ARRAY [0 .. NRegs] OF Operand;
        ftop_inmem := FALSE;
      METHODS
        wrFlush ();
        set_obj (obj: M3ObjFile.T);
        set_current_proc (p: x86Proc);
        set_textsym(sym: INTEGER);
        intCall (lab: Label);
        relCall (rel: INTEGER);
        absCall (p: x86Proc);
        rmCall (READONLY op: Operand);
        cleanretOp (psize: INTEGER);
        brOp (br: Cond; label: Label);
        setccOp (READONLY op: Operand; cond: Cond);
        noargOp (op: Op);
        noargFOp (op: FOp);
        immFOp (op: FOp; im: FIm);
        binFOp (op: FOp; st: INTEGER);
        memFOp (op: FOp; mvar: MVar);
        assert_fstack (count: INTEGER);
        f_ensureloaded ();
        f_exitproc ();
        f_pushnew ();
        fstack_push (READONLY mvar: MVar; nomem := FALSE);
        fstack_pop (READONLY mvar: MVar);
        fstack_swap ();
        fstack_discard ();
        f_loadlit (READONLY flarr: FloatBytes; type: MType);
        immOp (op: Op; READONLY dest: Operand; READONLY imm: TIntN.T);
        binOp (op: Op; READONLY dest, src: Operand);
        tableOp (op: Op; READONLY dest, index: Operand; scale: INTEGER;
                 table: MVar);
        swapOp (READONLY dest, src: Operand);
        movOp (READONLY dest, src: Operand);
        movDummyReloc (READONLY dest: Operand; sym: INTEGER);
        movImmT (READONLY dest: Operand; imm: TIntN.T);
        movImmI (READONLY dest: Operand; imm: INTEGER);
        MOVSWOp ();
        STOSWOp ();
        CBWOp ();
        lock_exchange (READONLY dest, src: Operand; type: Type);
        lock_compare_exchange (READONLY dest, src: Operand; type: Type);
        write_lock_prefix ();
        pushOp (READONLY src: Operand);
        popOp (READONLY dest: Operand);
        incOp (READONLY op: Operand);
        decOp (READONLY op: Operand);
        bitTestAndSetOp (READONLY bits, index: Operand); (* we don't care about test -- set_singleton *)
        bitTestOp (READONLY bits, index: Operand); (* set_member *)
        unOp (op: Op; READONLY dest: Operand);
        mulOp (READONLY src: Operand);
        imulOp (READONLY dest, src: Operand);
        imulImm (READONLY dest, src: Operand; imm: INTEGER; imsize: CARDINAL);
        divOp (READONLY divisor: Operand);
        idivOp (READONLY divisor: Operand);
        diffdivOp (READONLY divisor: Operand; apos: BOOLEAN);
        diffmodOp (READONLY divisor: Operand; apos: BOOLEAN);
        allocate_temp (var: x86Var; size, align: INTEGER);
        reserve_labels (n: INTEGER; short := FALSE): Label;
        set_label (label: Label; offset := 0);
        case_jump (READONLY index: Operand; READONLY label: ARRAY OF Label);
        load_ind (r: Regno; READONLY ind: Operand; o: ByteOffset;
                  type: MType);
        fast_load_ind (r: Regno; READONLY ind: Operand; o: ByteOffset;
                       size: INTEGER);
        store_ind (READONLY val, ind: Operand; o: ByteOffset; type: MType);
        f_loadind (READONLY ind: Operand; o: ByteOffset; type: MType);
        f_storeind (READONLY ind: Operand; o: ByteOffset; type: MType);
        log_label_init (var: x86Var; o: ByteOffset; lab: Label);
        get_frame (r: Regno; target, current: x86Proc);
        set_error_handler (err: ErrorHandler);
        init ();
        end ();
      END;
B is unsigned below A is unsigned above L is signed less G is signed greater B for unsigned below is also known as C for carry below and less are roughly synonyms in English, but one applies to unsigned, the other signed likewise for above and greater
TYPE Cond =                          { Z,   NZ,   E,   NE,   G,   GE,   L,   LE,   A,   AE,   B,   BE,   Always };
CONST CondName = ARRAY Cond OF TEXT { "Z", "NZ", "E", "NE", "G", "GE", "L", "LE", "A", "AE", "B", "BE", "*" };

CONST revcond = ARRAY Cond OF Cond
  { Cond.Z, Cond.NZ, Cond.E, Cond.NE, Cond.L, Cond.LE,
    Cond.G, Cond.GE, Cond.B, Cond.BE, Cond.A, Cond.AE, Cond.Always };

CONST unscond = ARRAY Cond OF Cond
  { Cond.Z, Cond.NZ, Cond.E, Cond.NE, Cond.A, Cond.AE,
    Cond.B, Cond.BE, Cond.A, Cond.AE, Cond.B, Cond.BE, Cond.Always };

TYPE
  BrOpCode = RECORD
    name: TEXT;
    rel8: INTEGER;
  END;

CONST bropcode = ARRAY Cond OF BrOpCode
  { BrOpCode { "JE",  16_74 },
    BrOpCode { "JNE", 16_75 },
    BrOpCode { "JE",  16_74 },
    BrOpCode { "JNE", 16_75 },
    BrOpCode { "JG",  16_7F },
    BrOpCode { "JGE", 16_7D },
    BrOpCode { "JL",  16_7C },
    BrOpCode { "JLE", 16_7E },
    BrOpCode { "JA",  16_77 },
    BrOpCode { "JAE", 16_73 },
    BrOpCode { "JB",  16_72 },
    BrOpCode { "JBE", 16_76 },
    BrOpCode { "JMP", -1    } };

TYPE
  CondOpCode = RECORD
    name: TEXT;
    opc: INTEGER;
  END;

CONST condopcode = ARRAY Cond OF CondOpCode
  { CondOpCode { "SETE",  16_94 },
    CondOpCode { "SETNE", 16_95 },
    CondOpCode { "SETE",  16_94 },
    CondOpCode { "SETNE", 16_95 },
    CondOpCode { "SETG",  16_9F },
    CondOpCode { "SETGE", 16_9D },
    CondOpCode { "SETL",  16_9C },
    CondOpCode { "SETLE", 16_9E },
    CondOpCode { "SETA",  16_97 },
    CondOpCode { "SETAE", 16_93 },
    CondOpCode { "SETB",  16_92 },
    CondOpCode { "SETBE", 16_96 },
    CondOpCode { "",      -1    } };

TYPE
  FloatBytes = ARRAY [0..7] OF TFloat.Byte;

TYPE
  FOpCode = RECORD
    name: TEXT;
    m32, m64, memop, stbase, stmodrm,
    stackdiff, memdiff, stackin, min: INTEGER;
    takesmem: BOOLEAN;
  END;

TYPE FOp = { fCOM, fCOMP, fCOMPP, fDECSTP, fINCSTP, fFREE,
             fNCLEX, fABS,
             fCHS, fNSTSWAX, fILD, fISTP, fLDCW, fSTCW,
             fLD, fSTP, fADDP, fSUBP, fSUBPR, fMUL, fDIV,
             fNOP };

CONST fopcode = ARRAY FOp OF FOpCode
  { FOpCode { "FCOM",    -1,    -1,    0, 16_D8, 16_D0, 0,  0,  2, 0, FALSE },
    FOpCode { "FCOM",    16_D8, 16_DC, 3, 16_D8, 16_D8, -2, -1, 2, 1, TRUE  },
    FOpCode { "FCOMP",   -1,    -1,    0, 16_DE, 16_D8, -2, 0,  2, 0, FALSE },
    FOpCode { "FDECSTP", -1,    -1,    0, 16_D9, 16_F6, 0,  0,  0, 0, FALSE },
    FOpCode { "FINCSTP", -1,    -1,    0, 16_D9, 16_F7, 0,  0,  0, 0, FALSE },
    FOpCode { "FFREE",   -1,    -1,    0, 16_DD, 16_C0, 0,  0,  0, 0, FALSE },
    FOpCode { "FNCLEX",  -1,    -1,    0, 16_DB, 16_E2, 0,  0,  0, 0, FALSE },
    FOpCode { "FABS",    -1,    -1,    0, 16_D9, 16_E1, 0,  0,  1, 0, FALSE },
    FOpCode { "FCHS",    -1,    -1,    0, 16_D9, 16_E0, 0,  0,  1, 0, FALSE },
    FOpCode { "FNSTSWAX",-1,    -1,    0, 16_DF, 16_E0, 0,  0,  0, 0, FALSE },
    FOpCode { "FILD",    16_DB, -1,    0, -1,    -1,    1,  1,  0, 0, FALSE },
    FOpCode { "FIST",    16_DB, -1,    3, -1,    -1,    -1, -1, 1, 1, FALSE },
    FOpCode { "FLDCW",   16_D9, -1,    5, -1,    -1,    0,  0,  0, 0, FALSE },
    FOpCode { "FSTCW",   16_D9, -1,    7, -1,    -1,    0,  0,  0, 0, FALSE },
    FOpCode { "FLD",     16_D9, 16_DD, 0, 16_D9, 16_C0, 1,  1,  0, 0, TRUE  },
    FOpCode { "FST",     16_D9, 16_DD, 3, 16_DD, 16_D8, -1, -1, 2, 1, TRUE  },
    FOpCode { "FADD",    16_D8, 16_DC, 0, 16_DE, 16_C0, -1, 0,  2, 1, TRUE  },
    FOpCode { "FSUB",    16_D8, 16_DC, 4, 16_DE, 16_E8, -1, 0,  2, 1, TRUE  },
    FOpCode { "FSUBR",   16_D8, 16_DC, 5, 16_DE, 16_E0, -1, 0,  2, 1, TRUE  },
    FOpCode { "FMUL",    16_D8, 16_DC, 1, 16_DE, 16_C8, -1, 0,  2, 1, TRUE  },
    FOpCode { "FDIV",    16_D8, 16_DC, 6, 16_DE, 16_F8, -1, 0,  2, 1, TRUE  },
    FOpCode { "FNOP",    -1,    -1,    0, -1,    -1,    0,  0,  0, 0, FALSE }};

TYPE
  FImOp = RECORD
    name: TEXT;
    opcode: INTEGER;
  END;

TYPE FIm = { ONE, L2T, L2E, PI, LG2, LN2, Z };

CONST FImName = ARRAY FIm OF TEXT { "1.0", "Log2(10)", "Log2(e)", "pi",
                                    "Log10(2)", "LogE(2)", "0.0" };

CONST imcode = ARRAY FIm OF FImOp
  { FImOp { "FLD1",   16_D9E8 },
    FImOp { "FLDL2T", 16_D9E9 },
    FImOp { "FLDL2E", 16_D9EA },
    FImOp { "FLDPI",  16_D9EB },
    FImOp { "FLDLG2", 16_D9EC },
    FImOp { "FLDLN2", 16_D9ED },
    FImOp { "FLDZ",   16_D9EE } };

TYPE
  OpCode = RECORD
    name: TEXT;
    (* rmr means dest is in register or memory, source is in register
     * rrm means dest is in register, source is in register or memory
     *  "op r/m,r" or "op r,r/m", given Intel syntax where dest
     * is on the left. The values undergo varous increments
     * depending on operand size and such; confusing.
     * immop is the "reg" value or second operand byte in like 12/3, the 3.
     * This table and x86 instruction encoding are NOT easy to understand.
     *)
    Aimm32, imm8, imm32, immop, rmr, rrm: INTEGER;
  END;

TYPE Op = { oAND,   oXOR,   oOR,    oMOV,   oADD,  oADC,  oSUB,   oSBB,
            oCMP,   oNEG,   oNOT,   oLEA,   oSHL,  oSAR,  oSHR,   oSHLD,
            oSHRD,  oROL,   oROR,   oSAHF,  oWAIT, oCLD,  oSTD,   oREP,
            oMOVSB, oMOVSD, oSTOSB, oSTOSD, oCWDE, oCDQ,  oLEAVE, oRET,
            oNOP, oXCHG, oXADD };

CONST opcode = ARRAY Op OF OpCode
  { OpCode { "AND",  16_25, 16_83, 16_81, 4, 16_20, 16_22 },
    OpCode { "XOR",  16_35, 16_83, 16_81, 6, 16_30, 16_32 },
    OpCode { "OR",   16_0D, 16_83, 16_81, 1, 16_08, 16_0A },
    OpCode { "MOV",  -1,    -1,    -1,    0, 16_88, 16_8A },
    OpCode { "ADD",  16_05, 16_83, 16_81, 0, 16_00, 16_02 },
    OpCode { "ADC",  16_15, 16_83, 16_81, 2, 16_10, 16_12 },
    OpCode { "SUB",  16_2D, 16_83, 16_81, 5, 16_28, 16_2A },
    OpCode { "SBB",  16_1D, 16_83, 16_81, 3, 16_18, 16_1A },
    OpCode { "CMP",  16_3D, 16_83, 16_81, 7, 16_38, 16_3A },
    OpCode { "NEG",  -1,    -1,    16_F6, 3, -1,    -1    },
    OpCode { "NOT",  -1,    -1,    16_F6, 2, -1,    -1    },
    OpCode { "LEA",  -1,    -1,    -1,    0, -1,    16_8C },
    OpCode { "SHL",  -1,    16_C1, 16_D2, 4, 16_D3, -1    }, (* rmr is reg/mem/cl, not reg/mem/anyreg *)
    OpCode { "SAR",  -1,    16_C1, 16_D2, 7, 16_D3, -1    }, (* rmr is reg/mem/cl, not reg/mem/anyreg *)
    OpCode { "SHR",  -1,    16_C1, 16_D2, 5, 16_D3, -1    }, (* rmr is reg/mem/cl, not reg/mem/anyreg *)
    OpCode { "SHLD", -1,    16_A4, -1,   -1, 16_A5, -1    }, (* third register always CL, imsize always 1 *)
    OpCode { "SHRD", -1,    16_AC, -1,   -1, 16_AD, -1    }, (* third register always CL, imsize always 1 *)
    OpCode { "ROL",  -1,    16_C1, 16_D2, 0, -1,    -1    },
    OpCode { "ROR",  -1,    16_C1, 16_D2, 1, -1,    -1    },
    OpCode { "SAHF", -1,    -1,    16_9E, 0, -1,    -1    },
    OpCode { "WAIT", -1,    -1,    16_9B, 0, -1,    -1    },
    OpCode { "CLD",  -1,    -1,    16_FC, 0, -1,    -1    },
    OpCode { "STD",  -1,    -1,    16_FD, 0, -1,    -1    },
    OpCode { "REP",  -1,    -1,    16_F3, 0, -1,    -1    },
    OpCode { "MOVSB",-1,    -1,    16_A4, 0, -1,    -1    },
    OpCode { "MOVSD",-1,    -1,    16_A5, 0, -1,    -1    },
    OpCode { "STOSB",-1,    -1,    16_AA, 0, -1,    -1    },
    OpCode { "STOSD",-1,    -1,    16_AB, 0, -1,    -1    },
    OpCode { "CWDE", -1,    -1,    16_98, 0, -1,    -1    },
    OpCode { "CDQ",  -1,    -1,    16_99, 0, -1,    -1    },
    OpCode { "LEAVE",-1,    -1,    16_C9, 0, -1,    -1    },
    OpCode { "RET"  ,-1,    -1,    16_C3, 0, -1,    -1    },
    OpCode { "NOP",  -1,    -1,    -1,    0, -1,    -1    },
    OpCode { "XCHG", 16_86, 16_86, 16_86, 16_86, 16_86, 16_86 }, (* hack; cleanup *)
    OpCode { "XADD", -1,    -1,    -1,   -1, 16_C1, -1    }
    };

PROCEDURE New (parent: M3x86Rep.U; wr: Wrx86.T): T;

END Codex86.