home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / adav313.zip / gnat-3_13p-os2-bin-20010916.zip / emx / gnatlib / s-mastop.adb < prev    next >
Text File  |  2000-07-19  |  21KB  |  584 lines

  1. ------------------------------------------------------------------------------
  2. --                                                                          --
  3. --                         GNAT COMPILER COMPONENTS                         --
  4. --                                                                          --
  5. --                     SYSTEM.MACHINE_STATE_OPERATIONS                      --
  6. --                                                                          --
  7. --                                 B o d y                                  --
  8. --                            (Version for x86)                             --
  9. --                                                                          --
  10. --                            $Revision: 1.6 $
  11. --                                                                          --
  12. --              Copyright (C) 1999 Ada Core Technologies, Inc.              --
  13. --                                                                          --
  14. -- GNAT is free software;  you can  redistribute it  and/or modify it under --
  15. -- terms of the  GNU General Public License as published  by the Free Soft- --
  16. -- ware  Foundation;  either version 2,  or (at your option) any later ver- --
  17. -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
  18. -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
  19. -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
  20. -- for  more details.  You should have  received  a copy of the GNU General --
  21. -- Public License  distributed with GNAT;  see file COPYING.  If not, write --
  22. -- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
  23. -- MA 02111-1307, USA.                                                      --
  24. --                                                                          --
  25. -- As a special exception,  if other files  instantiate  generics from this --
  26. -- unit, or you link  this unit with other files  to produce an executable, --
  27. -- this  unit  does not  by itself cause  the resulting  executable  to  be --
  28. -- covered  by the  GNU  General  Public  License.  This exception does not --
  29. -- however invalidate  any other reasons why  the executable file  might be --
  30. -- covered by the  GNU Public License.                                      --
  31. --                                                                          --
  32. -- GNAT was originally developed  by the GNAT team at  New York University. --
  33. -- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
  34. --                                                                          --
  35. ------------------------------------------------------------------------------
  36.  
  37. --  Note: it is very important that this unit not generate any exception
  38. --  tables of any kind. Otherwise we get a nasty rtsfind recursion problem.
  39. --  This means no subprograms, including implicitly generated ones.
  40.  
  41. with Unchecked_Conversion;
  42. with System.Storage_Elements;
  43. with System.Machine_Code; use System.Machine_Code;
  44.  
  45. package body System.Machine_State_Operations is
  46.  
  47.    use System.Exceptions;
  48.  
  49.    type Uns8  is mod 2 ** 8;
  50.    type Uns32 is mod 2 ** 32;
  51.  
  52.    type Bits5 is mod 2 ** 5;
  53.    type Bits6 is mod 2 ** 6;
  54.  
  55.    function To_Address is new Unchecked_Conversion (Uns32, Address);
  56.  
  57.    function To_Uns32 is new Unchecked_Conversion (Integer,  Uns32);
  58.    function To_Uns32 is new Unchecked_Conversion (Address,  Uns32);
  59.  
  60.    type Uns32_Ptr is access all Uns32;
  61.    function To_Uns32_Ptr is new Unchecked_Conversion (Address, Uns32_Ptr);
  62.    function To_Uns32_Ptr is new Unchecked_Conversion (Uns32,   Uns32_Ptr);
  63.  
  64.    --  Note: the type Uns32 has an alignment of 4. However, in some cases
  65.    --  values of type Uns32_Ptr will not be aligned (notably in the case
  66.    --  where we get the immediate field from an instruction). However this
  67.    --  does not matter in practice, since the x86 does not require that
  68.    --  operands be aligned.
  69.  
  70.    ----------------------
  71.    -- General Approach --
  72.    ----------------------
  73.  
  74.    --  For the x86 version of this unit, the Subprogram_Info_Type values
  75.    --  are simply the starting code address for the subprogram. Popping
  76.    --  of stack frames works by analyzing the code in the prolog, and
  77.    --  deriving from this analysis the necessary information for restoring
  78.    --  the registers, including the return point.
  79.  
  80.    ---------------------------
  81.    -- Description of Prolog --
  82.    ---------------------------
  83.  
  84.    --  If a frame pointer is present, the prolog looks like
  85.  
  86.    --     pushl %ebp
  87.    --     movl  %esp,%ebp
  88.    --     subl  $nnn,%esp     omitted if nnn = 0
  89.    --     pushl %edi          omitted if edi not used
  90.    --     pushl %esi          omitted if esi not used
  91.    --     pushl %ebx          omitted if ebx not used
  92.  
  93.    --  If a frame pointer is not present, the prolog looks like
  94.  
  95.    --     subl  $nnn,%esp     omitted if nnn = 0
  96.    --     pushl %ebp          omitted if ebp not used
  97.    --     pushl %edi          omitted if edi not used
  98.    --     pushl %esi          omitted if esi not used
  99.    --     pushl %ebx          omitted if ebx not used
  100.  
  101.    --  Note: any or all of the save over call registers may be used and
  102.    --  if so, will be saved using pushl as shown above. The order of the
  103.    --  pushl instructions will be as shown above for gcc generated code,
  104.    --  but the code in this unit does not assume this.
  105.  
  106.    -------------------------
  107.    -- Description of Call --
  108.    -------------------------
  109.  
  110.    --  A call looks like:
  111.  
  112.    --     pushl ...           push parameters
  113.    --     pushl ...
  114.    --     call  ...           perform the call
  115.    --     addl  $nnn,%esp     omitted if no parameters
  116.  
  117.    --  Note that we are not absolutely guaranteed that the call is always
  118.    --  followed by an addl operation that readjusts %esp for this particular
  119.    --  call. There are two reasons for this:
  120.  
  121.    --    1) The addl can be delayed and combined in the case where more than
  122.    --       one call appears in sequence. This can be suppressed by using the
  123.    --       switch -fno-defer-pop and for Ada code, we automatically use
  124.    --       this switch, but we could still be dealing with C code that was
  125.    --       compiled without using this switch.
  126.  
  127.    --    2) Scheduling may result in moving the addl instruction away from
  128.    --       the call. It is not clear if this actually can happen at the
  129.    --       current time, but it is certainly conceptually possible.
  130.  
  131.    --  The addl after the call is important, since we need to be able to
  132.    --  restore the proper %esp value when we pop the stack. However, we do
  133.    --  not try to compensate for either of the above effects. As noted above,
  134.    --  case 1 does not occur for Ada code, and it does not appear in practice
  135.    --  that case 2 occurs with any significant frequency (we have never seen
  136.    --  an example so far for gcc generated code).
  137.  
  138.    --  Furthermore, it is only in the case of -fomit-frame-pointer that we
  139.    --  really get into trouble from not properly restoring %esp. If we have
  140.    --  a frame pointer, then the worst that happens is that %esp is slightly
  141.    --  more depressed than it should be. This could waste a bit of space on
  142.    --  the stack, and even in some cases cause a storage leak on the stack,
  143.    --  but it will not affect the functional correctness of the processing.
  144.  
  145.    ----------------------------------------
  146.    -- Definitions of Instruction Formats --
  147.    ----------------------------------------
  148.  
  149.    type Rcode is (eax, ecx, edx, ebx, esp, ebp, esi, edi);
  150.    pragma Warnings (Off, Rcode);
  151.    --  Code indicating which register is referenced in an instruction
  152.  
  153.    --  The following define the format of a pushl instruction
  154.  
  155.    Op_pushl : constant Bits5 := 2#01010#;
  156.  
  157.    type Ins_pushl is record
  158.       Op  : Bits5 := Op_pushl;
  159.       Reg : Rcode;
  160.    end record;
  161.  
  162.    for Ins_pushl use record
  163.       Op  at 0 range 3 .. 7;
  164.       Reg at 0 range 0 .. 2;
  165.    end record;
  166.  
  167.    Ins_pushl_ebp : constant Ins_pushl := (Op_pushl, Reg => ebp);
  168.  
  169.    type Ins_pushl_Ptr is access all Ins_pushl;
  170.  
  171.    --  For the movl %esp,%ebp instruction, we only need to know the length
  172.    --  because we simply skip past it when we analyze the prolog.
  173.  
  174.    Ins_movl_length : constant := 2;
  175.  
  176.    --  The following define the format of addl/subl esp instructions
  177.  
  178.    Op_Immed : constant Bits6 := 2#100000#;
  179.  
  180.    Op2_addl_Immed : constant Bits5 := 2#11100#;
  181.    Op2_subl_Immed : constant Bits5 := 2#11101#;
  182.  
  183.    type Word_Byte is (Word, Byte);
  184.  
  185.    type Ins_addl_subl_byte is record
  186.       Op   : Bits6;           -- Set to Op_Immed
  187.       w    : Word_Byte;       -- Word/Byte flag (set to 1 = byte)
  188.       s    : Boolean;         -- Sign extension bit (1 = extend)
  189.       Op2  : Bits5;           -- Secondary opcode
  190.       Reg  : Rcode;           -- Register
  191.       Imm8 : Uns8;            -- Immediate operand
  192.    end record;
  193.  
  194.    for Ins_addl_subl_byte use record
  195.       Op   at 0 range 2 .. 7;
  196.       w    at 0 range 1 .. 1;
  197.       s    at 0 range 0 .. 0;
  198.       Op2  at 1 range 3 .. 7;
  199.       Reg  at 1 range 0 .. 2;
  200.       Imm8 at 2 range 0 .. 7;
  201.    end record;
  202.  
  203.    type Ins_addl_subl_word is record
  204.       Op    : Bits6;          -- Set to Op_Immed
  205.       w     : Word_Byte;      -- Word/Byte flag (set to 0 = word)
  206.       s     : Boolean;        -- Sign extension bit (1 = extend)
  207.       Op2   : Bits5;          -- Secondary opcode
  208.       Reg   : Rcode;          -- Register
  209.       Imm32 : Uns32;          -- Immediate operand
  210.    end record;
  211.  
  212.    for Ins_addl_subl_word use record
  213.       Op    at 0 range 2 .. 7;
  214.       w     at 0 range 1 .. 1;
  215.       s     at 0 range 0 .. 0;
  216.       Op2   at 1 range 3 .. 7;
  217.       Reg   at 1 range 0 .. 2;
  218.       Imm32 at 2 range 0 .. 31;
  219.    end record;
  220.  
  221.    type Ins_addl_subl_byte_Ptr is access all Ins_addl_subl_byte;
  222.    type Ins_addl_subl_word_Ptr is access all Ins_addl_subl_word;
  223.  
  224.    ---------------------
  225.    -- Prolog Analysis --
  226.    ---------------------
  227.  
  228.    --  The analysis of the prolog answers the following questions:
  229.  
  230.    --    1. Is %ebp used as a frame pointer?
  231.    --    2. How far is SP depressed (i.e. what is the stack frame size)
  232.    --    3. Which registers are saved in the prolog, and in what order
  233.  
  234.    --  The following data structure stores the answers to these questions
  235.  
  236.    subtype SOC is Rcode range ebx .. edi;
  237.    --  Possible save over call registers
  238.  
  239.    SOC_Max : constant := 4;
  240.    --  Max number of SOC registers that can be pushed
  241.  
  242.    type SOC_Push_Regs_Type is array (1 .. 4) of Rcode;
  243.    --  Used to hold the register codes of pushed SOC registers
  244.  
  245.    type Prolog_Type is record
  246.  
  247.       Frame_Reg : Boolean;
  248.       --  This is set to True if %ebp is used as a frame register, and
  249.       --  False otherwise (in the False case, %ebp may be saved in the
  250.       --  usual manner along with the other SOC registers).
  251.  
  252.       Frame_Length : Uns32;
  253.       --  Amount by which ESP is decremented on entry, includes the effects
  254.       --  of push's of save over call registers as indicated above, e.g. if
  255.       --  the prolog of a routine is:
  256.       --
  257.       --    pushl %ebp
  258.       --    movl %esp,%ebp
  259.       --    subl $424,%esp
  260.       --    pushl %edi
  261.       --    pushl %esi
  262.       --    pushl %ebx
  263.       --
  264.       --  Then the value of Frame_Length would be 436 (424 + 3 * 4). A
  265.       --  precise definition is that it is:
  266.       --
  267.       --    %esp on entry   minus   %esp after last SOC push
  268.       --
  269.       --  That definition applies both in the frame pointer present and
  270.       --  the frame pointer absent cases.
  271.  
  272.       Num_SOC_Push : Integer range 0 .. SOC_Max;
  273.       --  Number of save over call registers actually saved by pushl
  274.       --  instructions (other than the initial pushl to save the frame
  275.       --  pointer if a frame pointer is in use).
  276.  
  277.       SOC_Push_Regs : SOC_Push_Regs_Type;
  278.       --  The First Num_SOC_Push entries of this array are used to contain
  279.       --  the codes for the SOC registers, in the order in which they were
  280.       --  pushed. Note that this array excludes %ebp if it is used as a frame
  281.       --  register, since although %ebp is still considered an SOC register
  282.       --  in this case, it is saved and restored by a separate mechanism.
  283.       --  Also we will never see %esp represented in this list. Again, it is
  284.       --  true that %esp is saved over call, but it is restored by a separate
  285.       --  mechanism.
  286.  
  287.    end record;
  288.  
  289.    procedure Analyze_Prolog (A : Address; Prolog : out Prolog_Type);
  290.    --  Given the address of the start of the prolog for a procedure,
  291.    --  analyze the instructions of the prolog, and set Prolog to contain
  292.    --  the information obtained from this analysis.
  293.  
  294.    ----------------------------------
  295.    -- Machine_State_Representation --
  296.    ----------------------------------
  297.  
  298.    --  The type Machine_State is defined in the body of Ada.Exceptions as
  299.    --  a Storage_Array of length 1 .. Machine_State_Length. But really it
  300.    --  has structure as defined here. We use the structureless declaration
  301.    --  in Ada.Exceptions to avoid this unit from being implementation
  302.    --  dependent. The actual definition of Machine_State is as follows:
  303.  
  304.    type SOC_Regs_Type is array (SOC) of Uns32;
  305.  
  306.    type MState is record
  307.       eip : Uns32;
  308.       --  The instruction pointer location (which is the return point
  309.       --  value from the next level down in all cases).
  310.  
  311.       Regs : SOC_Regs_Type;
  312.       --  Values of the save over call registers
  313.    end record;
  314.  
  315.    for MState use record
  316.       eip  at 0 range 0 .. 31;
  317.       Regs at 4 range 0 .. 5 * 32 - 1;
  318.    end record;
  319.    --  Note: the routines Enter_Handler, and Set_Machine_State reference
  320.    --  the fields in this structure non-symbolically.
  321.  
  322.    type MState_Ptr is access all MState;
  323.  
  324.    function To_MState_Ptr is
  325.      new Unchecked_Conversion (Machine_State, MState_Ptr);
  326.  
  327.    ----------------------------
  328.    -- Allocate_Machine_State --
  329.    ----------------------------
  330.  
  331.    function Allocate_Machine_State return Machine_State is
  332.  
  333.       use System.Storage_Elements;
  334.  
  335.       function Gnat_Malloc (Size : Storage_Offset) return Machine_State;
  336.       pragma Import (C, Gnat_Malloc, "__gnat_malloc");
  337.  
  338.    begin
  339.       return Gnat_Malloc (MState'Max_Size_In_Storage_Elements);
  340.    end Allocate_Machine_State;
  341.  
  342.    --------------------
  343.    -- Analyze_Prolog --
  344.    --------------------
  345.  
  346.    procedure Analyze_Prolog (A : Address; Prolog : out Prolog_Type) is
  347.       Ptr : Address;
  348.       Ppl : Ins_pushl_Ptr;
  349.       Pas : Ins_addl_subl_byte_Ptr;
  350.  
  351.       function To_Ins_pushl_Ptr is
  352.         new Unchecked_Conversion (Address, Ins_pushl_Ptr);
  353.  
  354.       function To_Ins_addl_subl_byte_Ptr is
  355.         new Unchecked_Conversion (Address, Ins_addl_subl_byte_Ptr);
  356.  
  357.       function To_Ins_addl_subl_word_Ptr is
  358.         new Unchecked_Conversion (Address, Ins_addl_subl_word_Ptr);
  359.  
  360.    begin
  361.       Ptr := A;
  362.       Prolog.Frame_Length := 0;
  363.  
  364.       if Ptr = Null_Address then
  365.          Prolog.Num_SOC_Push := 0;
  366.          Prolog.Frame_Reg := True;
  367.          return;
  368.       end if;
  369.  
  370.       if To_Ins_pushl_Ptr (Ptr).all = Ins_pushl_ebp then
  371.          Ptr := Ptr + 1 + Ins_movl_length;
  372.          Prolog.Frame_Reg := True;
  373.       else
  374.          Prolog.Frame_Reg := False;
  375.       end if;
  376.  
  377.       Pas := To_Ins_addl_subl_byte_Ptr (Ptr);
  378.  
  379.       if Pas.Op = Op_Immed
  380.         and then Pas.Op2 = Op2_subl_Immed
  381.         and then Pas.Reg = esp
  382.       then
  383.          if Pas.w = Word then
  384.             Prolog.Frame_Length := Prolog.Frame_Length +
  385.                                      To_Ins_addl_subl_word_Ptr (Ptr).Imm32;
  386.             Ptr := Ptr + 6;
  387.  
  388.          else
  389.             Prolog.Frame_Length := Prolog.Frame_Length + Uns32 (Pas.Imm8);
  390.             Ptr := Ptr + 3;
  391.  
  392.             --  Note: we ignore sign extension, since a sign extended
  393.             --  value that was negative would imply a ludicrous frame size.
  394.          end if;
  395.       end if;
  396.  
  397.       --  Now scan push instructions for SOC registers
  398.  
  399.       Prolog.Num_SOC_Push := 0;
  400.  
  401.       loop
  402.          Ppl := To_Ins_pushl_Ptr (Ptr);
  403.  
  404.          if Ppl.Op = Op_pushl and then Ppl.Reg in SOC then
  405.             Prolog.Num_SOC_Push := Prolog.Num_SOC_Push + 1;
  406.             Prolog.SOC_Push_Regs (Prolog.Num_SOC_Push) := Ppl.Reg;
  407.             Prolog.Frame_Length := Prolog.Frame_Length + 4;
  408.             Ptr := Ptr + 1;
  409.  
  410.          else
  411.             exit;
  412.          end if;
  413.       end loop;
  414.  
  415.    end Analyze_Prolog;
  416.  
  417.    -------------------
  418.    -- Enter_Handler --
  419.    -------------------
  420.  
  421.    procedure Enter_Handler (M : Machine_State; Handler : Handler_Loc) is
  422.    begin
  423.       Asm ("mov %0,%%edx", Inputs => Machine_State'Asm_Input ("r", M));
  424.       Asm ("mov %0,%%eax", Inputs => Handler_Loc'Asm_Input ("r", Handler));
  425.  
  426.       Asm ("mov 4(%%edx),%%ebx");    -- M.Regs (ebx)
  427.       Asm ("mov 12(%%edx),%%ebp");   -- M.Regs (ebp)
  428.       Asm ("mov 16(%%edx),%%esi");   -- M.Regs (esi)
  429.       Asm ("mov 20(%%edx),%%edi");   -- M.Regs (edi)
  430.       Asm ("mov 8(%%edx),%%esp");    -- M.Regs (esp)
  431.       Asm ("jmp %*%%eax");
  432.    end Enter_Handler;
  433.  
  434.    ------------------------
  435.    -- Free_Machine_State --
  436.    ------------------------
  437.  
  438.    procedure Free_Machine_State (M : in out Machine_State) is
  439.       procedure Gnat_Free (M : in Machine_State);
  440.       pragma Import (C, Gnat_Free, "__gnat_free");
  441.  
  442.    begin
  443.       Gnat_Free (M);
  444.       M := Machine_State (Null_Address);
  445.    end Free_Machine_State;
  446.  
  447.    ------------------
  448.    -- Get_Code_Loc --
  449.    ------------------
  450.  
  451.    function Get_Code_Loc (M : Machine_State) return Code_Loc is
  452.  
  453.       Asm_Call_Size : constant := 2;
  454.       --  Minimum size for a call instruction under ix86. Using the minimum
  455.       --  size is safe here as the call point computed from the return point
  456.       --  will always be inside the call instruction.
  457.  
  458.       MS : constant MState_Ptr := To_MState_Ptr (M);
  459.  
  460.    begin
  461.       if MS.eip = 0 then
  462.          return To_Address (MS.eip);
  463.       else
  464.          --  When doing a call the return address is pushed to the stack.
  465.          --  We want to return the call point address, so we substract
  466.          --  Asm_Call_Size from the return address. This value is set
  467.          --  to 5 as an asm call takes 5 bytes on x86 architectures.
  468.  
  469.          return To_Address (MS.eip - Asm_Call_Size);
  470.       end if;
  471.    end Get_Code_Loc;
  472.  
  473.    --------------------------
  474.    -- Machine_State_Length --
  475.    --------------------------
  476.  
  477.    function Machine_State_Length
  478.      return System.Storage_Elements.Storage_Offset
  479.    is
  480.    begin
  481.       return MState'Max_Size_In_Storage_Elements;
  482.    end Machine_State_Length;
  483.  
  484.    ---------------
  485.    -- Pop_Frame --
  486.    ---------------
  487.  
  488.    procedure Pop_Frame
  489.      (M    : Machine_State;
  490.       Info : Subprogram_Info_Type)
  491.    is
  492.       MS  : constant MState_Ptr := To_MState_Ptr (M);
  493.       PL  : Prolog_Type;
  494.  
  495.       SOC_Ptr : Uns32;
  496.       --  Pointer to stack location after last SOC push
  497.  
  498.       Rtn_Ptr : Uns32;
  499.       --  Pointer to stack location containing return address
  500.  
  501.    begin
  502.       Analyze_Prolog (Info, PL);
  503.  
  504.       --  Case of frame register, use EBP, safer than ESP
  505.  
  506.       if PL.Frame_Reg then
  507.          SOC_Ptr := MS.Regs (ebp) - PL.Frame_Length;
  508.          Rtn_Ptr := MS.Regs (ebp) + 4;
  509.          MS.Regs (ebp) := To_Uns32_Ptr (MS.Regs (ebp)).all;
  510.  
  511.       --  No frame pointer, use ESP, and hope we have it exactly right!
  512.  
  513.       else
  514.          SOC_Ptr := MS.Regs (esp);
  515.          Rtn_Ptr := SOC_Ptr + PL.Frame_Length;
  516.       end if;
  517.  
  518.       --  Get saved values of SOC registers
  519.  
  520.       for J in reverse 1 .. PL.Num_SOC_Push loop
  521.          MS.Regs (PL.SOC_Push_Regs (J)) := To_Uns32_Ptr (SOC_Ptr).all;
  522.          SOC_Ptr := SOC_Ptr + 4;
  523.       end loop;
  524.  
  525.       MS.eip := To_Uns32_Ptr (Rtn_Ptr).all;
  526.       MS.Regs (esp) := Rtn_Ptr + 4;
  527.    end Pop_Frame;
  528.  
  529.    -----------------------
  530.    -- Set_Machine_State --
  531.    -----------------------
  532.  
  533.    procedure Set_Machine_State (M : Machine_State) is
  534.       N : constant Asm_Output_Operand := No_Output_Operands;
  535.  
  536.    begin
  537.       Asm ("mov %0,%%edx", N, Machine_State'Asm_Input ("r", M));
  538.  
  539.       --  At this stage, we have the following situation (note that we
  540.       --  are assuming that the -fomit-frame-pointer switch has not been
  541.       --  used in compiling this procedure.
  542.  
  543.       --     (value of M)
  544.       --     return point
  545.       --     old ebp          <------ current ebp/esp value
  546.  
  547.       --  The values of registers ebx/esi/edi are unchanged from entry
  548.       --  so they have the values we want, and %edx points to the parameter
  549.       --  value M, so we can store these values directly.
  550.  
  551.       Asm ("mov %%ebx,4(%%edx)");    -- M.Regs (ebx)
  552.       Asm ("mov %%esi,16(%%edx)");   -- M.Regs (esi)
  553.       Asm ("mov %%edi,20(%%edx)");   -- M.Regs (edi)
  554.  
  555.       --  The desired value of ebp is the old value
  556.  
  557.       Asm ("mov 0(%%ebp),%%eax");
  558.       Asm ("mov %%eax,12(%%edx)");   -- M.Regs (ebp)
  559.  
  560.       --  The return point is the desired eip value
  561.  
  562.       Asm ("mov 4(%%ebp),%%eax");
  563.       Asm ("mov %%eax,(%%edx)");   -- M.eip
  564.  
  565.       --  Finally, the desired %esp value is the value at the point of
  566.       --  call to this routine *before* pushing the parameter value.
  567.  
  568.       Asm ("lea 12(%%ebp),%%eax");
  569.       Asm ("mov %%eax,8(%%edx)");   -- M.Regs (esp)
  570.    end Set_Machine_State;
  571.  
  572.    ------------------------------
  573.    -- Set_Signal_Machine_State --
  574.    ------------------------------
  575.  
  576.    procedure Set_Signal_Machine_State
  577.      (M       : Machine_State;
  578.       Context : System.Address) is
  579.    begin
  580.       null;
  581.    end Set_Signal_Machine_State;
  582.  
  583. end System.Machine_State_Operations;
  584.