home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / PROG / PASCAL / ERROR87.ZIP / DECODE87.PAS next >
Encoding:
Pascal/Delphi Source File  |  1990-08-14  |  13.3 KB  |  448 lines

  1. unit decode87;
  2.  
  3.   { Unit to classify an 8087 instruction by its encoding }
  4. interface
  5. type
  6.   instruction =
  7.   (iF2XM1, iFABS, iFADD, iFADDP, iFBLD, iFBSTP, iFCHS, iFCLEX, iFCOM,
  8.    iFCOMP, iFCOMPP, iFCOS, iFDECSTP, iFDISI, iFDIV, iFDIVP, iFDIVR, iFDIVRP,
  9.    iFENI, iFFREE, iFIADD, iFICOM, iFICOMP, iFIDIV, iFIDIVR, iFILD, iFIMUL,
  10.    iFINCSTP, iFINIT, iFIST, iFISTP, iFISUB, iFISUBR, iFLD, iFLD1, iFLDCW,
  11.    iFLDENV, iFLDL2E, iFLDL2T, iFLDLG2, iFLDLN2, iFLDPI, iFLDZ, iFMUL, iFMULP,
  12.    iFNOP, iFPATAN, iFPREM, iFPREM1, iFPTAN, iFRNDINT, iFRSTOR, iFSAVE,
  13.    iFSCALE, iFSETPM, iFSIN, iFSINCOS, iFSQRT, iFST, iFSTCW, iFSTENV, iFSTP,
  14.    iFSTSW, iFSUB, iFSUBP, iFSUBR, iFSUBRP, iFTST, iFUCOM, iFUCOMP,
  15.    iFUCOMPP, iFXAM, iFXCH, iFXTRACT, iFYL2X, iFYL2XP1, iUnknown);
  16. const
  17.   inst_names : array[instruction] of String[7] =
  18.   ('F2XM1', 'FABS', 'FADD', 'FADDP', 'FBLD', 'FBSTP', 'FCHS', 'FCLEX', 'FCOM',
  19.    'FCOMP', 'FCOMPP', 'FCOS', 'FDECSTP', 'FDISI', 'FDIV', 'FDIVP', 'FDIVR', 'FDIVRP', 'FENI',
  20.    'FFREE', 'FIADD', 'FICOM', 'FICOMP', 'FIDIV', 'FIDIVR', 'FILD', 'FIMUL', 'FINCSTP',
  21.    'FINIT', 'FIST', 'FISTP', 'FISUB', 'FISUBR', 'FLD', 'FLD1', 'FLDCW', 'FLDENV', 'FLDL2E',
  22.    'FLDL2T', 'FLDLG2', 'FLDLN2', 'FLDPI', 'FLDZ', 'FMUL', 'FMULP', 'FNOP', 'FPATAN',
  23.    'FPREM', 'FPREM1', 'FPTAN', 'FRNDINT', 'FRSTOR', 'FSAVE', 'FSCALE', 'FSETPM', 'FSIN', 'FSINCOS', 'FSQRT', 'FST', 'FSTCW',
  24.    'FSTENV', 'FSTP', 'FSTSW', 'FSUB', 'FSUBP', 'FSUBR', 'FSUBRP', 'FTST', 'FUCOM',
  25.    'FUCOMP', 'FUCOMPP', 'FXAM', 'FXCH', 'FXTRACT', 'FYL2X', 'FYL2XP1', '');
  26. type
  27.   reg_count = 0..8;
  28.  
  29.   operand_type = (arReg0, arReg1, arReg2, arReg3, arReg4, arReg5, arReg6,
  30.                   arReg7, arWord, arLongint, arComp, arBCD,
  31.                   arSingle, arDouble, arExtended, arControl, arStatus,
  32.                   arEnviron, arState, arNone);
  33.   operand_set = set of operand_type;
  34. const
  35.   arg_names : array[operand_type] of String[8] =
  36.   ('Reg0', 'Reg1', 'Reg2', 'Reg3', 'Reg4', 'Reg5', 'Reg6',
  37.    'Reg7', 'Word', 'Longint', 'Comp', 'BCD',
  38.    'Single', 'Double', 'Extended', 'Control', 'Status',
  39.    'Environ', 'State', 'None');
  40.  
  41. type
  42.   opcode_info = record
  43.                   inst     : instruction;
  44.                   arg1, arg2 : operand_type;
  45.                 end;
  46.  
  47. procedure decode_opcode(opcode : Word; var result : opcode_info);
  48.  
  49. procedure operands_read(inst_info : opcode_info; var ops_read : operand_set);
  50.  
  51. function num_pops(inst_info : opcode_info) : reg_count;
  52.  
  53. function num_pushes(inst_info : opcode_info) : reg_count;
  54.  
  55. function limited(inst_info : opcode_info): boolean;
  56.  
  57. function lower_limit(inst_info : opcode_info) : extended;
  58.   { least legal operand }
  59.  
  60. function upper_limit(inst_info : opcode_info) : extended;
  61.   { greatest legal operand }
  62.  
  63.  
  64. implementation
  65. const
  66.   Plus_Infinity_Array : array[1..2] of word = (0, $7f80);
  67. var
  68.   Plus_Infinity : single absolute Plus_Infinity_Array;
  69. const
  70.   Minus_Infinity_Array : array[1..2] of word = (0, $ff80);
  71. var
  72.   Minus_Infinity : single absolute Minus_Infinity_Array;
  73.  
  74.   procedure operands_read(inst_info : opcode_info; var ops_read : operand_set);
  75.   const
  76.     reads_reg0 =
  77.     [iF2XM1, iFABS, iFADD, iFADDP, iFBSTP, iFCHS, iFCOM,
  78.     iFCOMP, iFCOMPP, iFCOS, iFDIV, iFDIVP, iFDIVR, iFDIVRP,
  79.     iFIADD, iFICOM, iFICOMP, iFIDIV, iFIDIVR, iFIMUL,
  80.     iFIST, iFISTP, iFISUB, iFISUBR, iFMUL, iFMULP,
  81.     iFPATAN, iFPREM, iFPREM1, iFPTAN, iFRNDINT,
  82.     iFSCALE, iFSIN, iFSINCOS, iFSQRT, iFST, iFSTP,
  83.     iFSUB, iFSUBP, iFSUBR, iFSUBRP, iFTST, iFUCOM, iFUCOMP,
  84.     iFUCOMPP, iFXAM, iFXCH, iFXTRACT, iFYL2X, iFYL2XP1];
  85.     reads_reg1 =
  86.     [iFPATAN, iFPREM, iFSCALE, iFYL2X, iFYL2XP1];
  87.     reads_arg1 =
  88.     [iFADD, iFADDP, iFBLD, iFCOM, iFCOMP, iFCOMPP, iFDIV, iFDIVP,
  89.     iFDIVR, iFDIVRP, iFIADD, iFICOM, iFICOMP, iFIDIV, iFIDIVR, iFILD, iFIMUL,
  90.     iFISUB, iFISUBR, iFLD, iFLDCW, iFLDENV, iFMUL, iFMULP,
  91.     iFRSTOR, iFSUB, iFSUBP, iFSUBR, iFSUBRP, iFTST, iFUCOM, iFUCOMP,
  92.     iFUCOMPP, iFXAM, iFXCH];
  93.  
  94.   begin
  95.     with inst_info do
  96.     begin
  97.       if inst in reads_reg0 then
  98.         ops_read := [arReg0]
  99.       else
  100.         ops_read := [];
  101.       if inst in reads_reg1 then
  102.         ops_read := ops_read+[arReg1];
  103.       if (arg1 <> arNone) and (inst in reads_arg1) then
  104.         ops_read := ops_read+[arg1];
  105.       if arg2 <> arNone then
  106.         ops_read := ops_read+[arg2];
  107.     end;
  108.   end;
  109.  
  110.   function num_pops(inst_info : opcode_info) : reg_count;
  111.   const
  112.     two_pop  = [iFCOMPP, iFUCOMPP];
  113.     pops =
  114.     [iFADDP, iFBSTP, iFCOMP, iFDIVP, iFDIVRP, iFICOMP, iFISTP, iFMULP,
  115.     iFPATAN, iFSTP, iFSUBP, iFSUBRP, iFUCOMP, iFYL2X, iFYL2XP1]+two_pop;
  116.   begin
  117.     if inst_info.inst in pops then
  118.       if inst_info.inst in two_pop then
  119.         num_pops := 2
  120.       else
  121.         num_pops := 1
  122.     else
  123.       num_pops := 0;
  124.   end;
  125.  
  126.   function num_pushes(inst_info : opcode_info) : reg_count;
  127.   const
  128.     does_push =
  129.     [iFBLD, iFILD, iFLD, iFLD1, iFLDL2E, iFLDL2T, iFLDLG2, iFLDLN2,
  130.     iFLDPI, iFLDZ, iFPTAN, iFSINCOS, iFXTRACT];
  131.   begin
  132.     if inst_info.inst in does_push then
  133.       num_pushes := 1
  134.     else
  135.       num_pushes := 0;
  136.   end;
  137.  
  138. function limited(inst_info:opcode_info):boolean;
  139. const
  140.   limited_instructions =
  141.   [iF2XM1 {0 to 0.5} , iFPATAN {0 < Y < X < pinf} ,
  142.   iFPTAN {0 to pi/4} , iFSCALE {won't cause exception, but -2^15<Y<2^15} ,
  143.   iFSQRT {0 to pinf} , iFYL2X {0 < X < pinf} ,
  144.   iFYL2XP1 {|X| < (1-1/sqrt(2))} ];
  145. begin
  146.   limited := inst_info.inst in limited_instructions;
  147. end;
  148.  
  149.  
  150.   function lower_limit(inst_info : opcode_info) : extended;
  151.   begin
  152.     if limited(inst_info) then
  153.       case inst_info.inst of
  154.         iF2XM1,
  155.         iFPATAN,
  156.         iFPTAN,
  157.         iFSQRT,
  158.         iFYL2X : lower_limit := 0.0;
  159.         iFSCALE : lower_limit := -32768;
  160.         iFYL2XP1 : lower_limit := -(1-1/Sqrt(2));
  161.       end
  162.     else
  163.       lower_limit := minus_infinity;
  164.   end;
  165.  
  166.   function upper_limit(inst_info : opcode_info) : extended;
  167.   begin
  168.     if limited(inst_info)  then
  169.       case inst_info.inst of
  170.         iF2XM1 : upper_limit := 0.5;
  171.         iFSQRT,
  172.         iFYL2X,
  173.         iFPATAN : upper_limit := plus_infinity;
  174.         iFPTAN : upper_limit := pi/4;
  175.         iFSCALE : upper_limit := 32768;
  176.         iFYL2XP1 : upper_limit := (1-1/Sqrt(2));
  177.       end
  178.     else
  179.       upper_limit := plus_infinity;
  180.   end;
  181.   procedure decode_opcode(opcode : Word; var result : opcode_info);
  182.  
  183.   { This routine and those within it are closely based on UNINLINE,
  184.     by L. David Baldwin. }
  185.  
  186.   var
  187.     opbyte1,
  188.     opbyte2,
  189.     rm,
  190.     mode,
  191.     middle   : Byte;
  192.     memory_reference : Boolean;
  193.  
  194.     procedure ReadModeByte;
  195.     {read the mode byte and sort out the various parts.  read the
  196.      displacement byte or word if req'D}
  197.     var Modebyte : Byte;
  198.     begin
  199.       Modebyte := opbyte2;
  200.       rm := Modebyte and 7;
  201.       mode := (Modebyte and $C0) div 64;
  202.       middle := (Modebyte and $38) div 8;
  203.       if (mode = 0) and (rm = 6) or (mode = 2) or (mode = 1) then
  204.         memory_reference := True;
  205.     end;
  206.  
  207.     procedure ST_i;               {do st(i) }
  208.     begin
  209.       result.arg1 := operand_type(Word(rm));
  210.     end;
  211.  
  212.     procedure STi_ST;             {do st(i),st }
  213.     begin
  214.       ST_i;
  215.       result.arg2 := arReg0;
  216.     end;
  217.  
  218.     procedure ST_STi;             { do st,st(i) }
  219.     begin
  220.       ST_i;
  221.       with result do
  222.       begin
  223.         arg2 := arg1;
  224.         arg1 := arReg0;
  225.       end;
  226.     end;
  227.  
  228.     procedure DB;
  229.     const inst_list : array[0..12] of instruction =
  230.       (iFILD, iUnknown, iFIST, iFISTP, iUnknown, iFLD, iUnknown,
  231.        iFSTP, iFENI, iFDISI, iFCLEX, iFINIT, iFSETPM);
  232.     var I    : Word;
  233.       Tmp      : instruction;
  234.     begin
  235.       ReadModeByte;
  236.       if (mode = 3) then
  237.         I := rm+8
  238.       else
  239.         I := middle;              {form an index}
  240.       Tmp := inst_list[I];
  241.       if (Tmp <> iUnknown) and (I <= 12) then
  242.       begin
  243.         result.inst := Tmp;
  244.         if I <= 3 then
  245.           result.arg1 := arLongint
  246.         else
  247.           if I <= 7 then
  248.             result.arg1 := arExtended
  249.       end
  250.       else
  251.         { Unknown! };
  252.     end;
  253.  
  254.     procedure DD;
  255.     const inst_list : array[0..13] of instruction =
  256.       (iFLD, iUnknown, iFST, iFSTP, iFRSTOR,
  257.        iUnknown, iFSAVE, iFSTSW, iFFREE, iFXCH,
  258.        iFST, iFSTP, iFUCOM, iFUCOMP);
  259.     var I    : Word;
  260.       Tmp      : instruction;
  261.     begin
  262.       ReadModeByte;
  263.       if mode = 3 then
  264.         I := middle+8
  265.       else
  266.         I := middle;
  267.       Tmp := inst_list[I];
  268.       if (Tmp <> iUnknown) and (I <= 13) then
  269.       begin
  270.         result.inst := Tmp;
  271.         if I <= 3 then
  272.           result.arg1 := arDouble
  273.         else if I <= 7 then
  274.           if I in [4, 6] then
  275.             result.arg1 := arState
  276.           else
  277.             result.arg1 := arStatus
  278.         else
  279.           ST_i;
  280.       end
  281.       else
  282.         { Unknown !};
  283.     end;
  284.  
  285.     procedure DF;
  286.     const inst_list : array[0..11] of instruction =
  287.       (iFILD, iUnknown, iFIST, iFISTP, iFBLD,
  288.        iFILD, iFBSTP, iFISTP, iFFREE, iFXCH,
  289.        iFST, iFSTP);
  290.     var I    : Word;
  291.     begin
  292.       ReadModeByte;
  293.       if mode = 3 then
  294.         I := middle+8
  295.       else
  296.         I := middle;              {form index}
  297.       if (I <> 1) and (I <= 11) then
  298.       begin
  299.         result.inst := inst_list[I];
  300.         if I <= 3 then
  301.           result.arg1 := arWord
  302.         else
  303.           if I <= 7 then
  304.           begin
  305.             if (I and 5) = 4 then
  306.               result.arg1 := arBCD
  307.             else
  308.               result.arg1 := arComp;
  309.           end
  310.         else
  311.           ST_i;
  312.       end
  313.       else
  314.         { Unknown !};
  315.     end;
  316.  
  317.     procedure D9;
  318.     const inst_list1 : array[0..11] of instruction =
  319.       (iFLD, iUnknown, iFST, iFSTP,
  320.        iFLDENV, iFLDCW, iFSTENV, iFSTCW,
  321.        iFLD, iFXCH, iFNOP, iFSTP);
  322.  
  323.     const inst_list2 : array[0..31] of instruction =
  324.       (iFCHS, iFABS, iUnknown, iUnknown, iFTST,
  325.        iFXAM, iUnknown, iUnknown, iFLD1, iFLDL2T,
  326.        iFLDL2E, iFLDPI, iFLDLG2, iFLDLN2, iFLDZ,
  327.        iUnknown, iF2XM1, iFYL2X, iFPTAN, iFPATAN,
  328.        iFXTRACT, iFPREM1, iFDECSTP, iFINCSTP, iFPREM,
  329.        iFYL2XP1, iFSQRT, iFSINCOS, iFRNDINT, iFSCALE,
  330.        iFSIN, iFCOS);
  331.     var I    : Word;
  332.       Tmp      : instruction;
  333.     begin
  334.       ReadModeByte;
  335.       if (mode <> 3) or (middle <= 3) then
  336.       begin
  337.         if mode = 3 then
  338.           I := middle+8
  339.         else
  340.           I := middle;
  341.         if (I = 1) or ((I = 10) and (rm <> 0)) then
  342.           { Unknown !}
  343.         else
  344.         begin
  345.           Tmp := inst_list1[I];
  346.           result.inst := Tmp;
  347.           if I <= 3 then
  348.             result.arg1 := arSingle
  349.           else if I <= 7 then
  350.             if I in [4, 6] then
  351.               result.arg1 := arEnviron
  352.             else
  353.               result.arg1 := arControl
  354.           else
  355.             if I <> 10 then       {fnop is 10}
  356.               ST_i;               {st(i)}
  357.         end;
  358.       end
  359.       else
  360.       begin                       {mode=3 and middle>=4}
  361.         I := rm+(middle and 3)*8; {include lower 2 bits of middle in index}
  362.         if (inst_list2[I] <> iUnknown) and (I <= 31) then
  363.           result.inst := inst_list2[I]
  364.         else
  365.           { unknown! };
  366.       end;
  367.     end;
  368.  
  369.     procedure D8_DC;
  370.     type Nametype = array[0..7] of instruction;
  371.     var Shortreal : Boolean;
  372.     const inst_list : Nametype = (
  373.       iFADD, iFMUL, iFCOM, iFCOMP, iFSUB, iFSUBR, iFDIV, iFDIVR);
  374.     begin
  375.       Shortreal := opbyte1 = $D8;
  376.       ReadModeByte;
  377.       if not Shortreal then
  378.         if (middle >= 6) then     {fdiv, fdivr are reversed here}
  379.           middle := middle xor 1;
  380.       result.inst := inst_list[middle];
  381.       if mode <> 3 then
  382.       begin
  383.         if Shortreal then
  384.           result.arg1 := arSingle
  385.         else
  386.           result.arg1 := arDouble
  387.       end
  388.       else                        {mode=3}
  389.         if Shortreal then
  390.           ST_STi
  391.       else
  392.         STi_ST;                   {add the stack info}
  393.     end;
  394.  
  395.     procedure DA_DE;
  396.     type Nametype = array[0..15] of instruction;
  397.     var ShortInt : Boolean;
  398.     const inst_list : Nametype = (
  399.       iFIADD, iFIMUL, iFICOM, iFICOMP, iFISUB, iFISUBR, iFIDIV,
  400.       iFIDIVR, iFADDP, iFMULP, iFCOMP, iFCOMPP, iFSUBRP, iFSUBP,
  401.       iFDIVRP, iFDIVP);
  402.     begin
  403.       ShortInt := opbyte1 = $DA;
  404.       ReadModeByte;
  405.       if mode <> 3 then
  406.       begin
  407.         result.inst := inst_list[middle];
  408.         if ShortInt then
  409.           result.arg1 := arLongint
  410.         else
  411.           result.arg1 := arWord;
  412.       end
  413.       else
  414.       begin                       {mode=3}
  415.         if ((middle = 3) and (rm <> 1)) then
  416.           { Unknown! }                  {not fl pt}
  417.         else
  418.           if ShortInt and (rm = 1) and (middle = 5) then
  419.             result.inst := iFUCOMPP
  420.         else
  421.         begin
  422.           result.inst := inst_list[middle+8];
  423.           if (middle <> 3) then
  424.             STi_ST;
  425.         end;
  426.       end;
  427.     end;
  428.  
  429.   begin                           { decode_opcode}
  430.     opbyte1 := Hi(opcode);
  431.     opbyte2 := Lo(opcode);
  432.     with result do
  433.     begin
  434.       inst := iUnknown;
  435.       arg1 := arNone;
  436.       arg2 := arNone;
  437.       case opbyte1 of
  438.         $DA, $DE : DA_DE;
  439.         $D8, $DC : D8_DC;
  440.         $D9 : D9;
  441.         $DB : DB;
  442.         $DD : DD;
  443.         $DF : DF;
  444.       end;
  445.     end;
  446.   end;
  447. end.
  448.