{$ifdef LINUX}
{$include ../defines.pas}
{$else}
{$include ..\defines.pas}
{$endif}
unit Service_fpu;

interface

uses fpu_types;

function significand (x: Pfpu_reg): pu64;
function exponent16 (x: Pfpu_reg): s16;
function addexponent (x: Pfpu_reg; y: s32): u32; // !!! controllare secondo parametro
procedure stdexp (x: Pfpu_reg);
function st (x: integer): PFPU_REG;

{$include fpu_const.pas}

function signbyte (a: PFPU_REG): pu_char;
function getsign (a: PFPU_REG): u_char;
procedure setsign (a: PFPU_REG; b: u_char);
procedure copysign (a: PFPU_REG; b: PFPU_REG);
procedure changesign (a: PFPU_REG);
procedure setpositive (a: PFPU_REG);
procedure setnegative (a: PFPU_REG);
function signpositive (a: PFPU_REG): u_char;
function signnegative (a: PFPU_REG): u_char;

function fpu_rm: pu_char;
procedure clear_C1;
procedure setexponent16 (x: PFPU_REG; y: s32);
function exponent (x: PFPU_REG): u32;
procedure setexponentpos (x: PFPU_REG; y: integer);

implementation

uses fpu_system;

function significand (x: Pfpu_reg): pu64;
  begin
{$ifdef EMU_BIG_ENDIAN}
  Result:=@x^.sigh;
{$else}
    Result := @x^.sigl;
{$endif}
  end;

function exponent16 (x: Pfpu_reg): s16;
  begin
    Result := x^.Exp;
  end;

function addexponent (x: Pfpu_reg; y: s32): u32;
  begin
    x^.exp := x^.exp + y;
  end;

procedure stdexp (x: Pfpu_reg);
  begin
    x^.exp := x^.exp + EXTENDED_Ebias;
  end;

function registers: pu_char;
  begin
  end;

function st (x: integer): PFPU_REG;
  begin
    Result := PFPU_REG(longint(register_base) + sizeof(FPU_REG) *
      ((I387.soft.ftop + x) and 7));
  end;

function signbyte (a: PFPU_REG): pu_char;
  var
    p: PChar;
  begin
    p := PChar(longint(a) + 9);
    Result := pu_char(p);
  end;

function getsign (a: PFPU_REG): u_char;
  begin
    Result := signbyte(a)^ and $80;
  end;

procedure setsign (a: PFPU_REG; b: u_char);
  begin
    if (b) <> 0 then
      pu_char(longint(a) + 8)^ := pu_char(longint(a) + 8)^ or $80
    else
      pu_char(longint(a) + 8)^ := pu_char(longint(a) + 8)^ and $7f;
  end;

procedure copysign (a: PFPU_REG; b: PFPU_REG);
  begin
    if (getsign(a) <> 0) then
      signbyte(b)^ := signbyte(b)^ or $80
    else
      signbyte(b)^ := $7f;
  end;

procedure changesign (a: PFPU_REG);
  begin
    signbyte(a)^ := signbyte(a)^ xor $80;
  end;

procedure setpositive (a: PFPU_REG);
  begin
    signbyte(a)^ := signbyte(a)^ and $7f;
  end;

procedure setnegative (a: PFPU_REG);
  begin
    signbyte(a)^ := signbyte(a)^ or $80;
  end;

function signpositive (a: PFPU_REG): u_char;
  begin
    Result := word((signbyte(a)^ and $80) = 0);
  end;

function signnegative (a: PFPU_REG): u_char;
  begin
    Result := word((signbyte(a)^ and $80));
  end;

function fpu_rm: pu_char;
  begin
    Result := pu_char(@I387.soft.rm);
  end;

procedure clear_C1;
  begin
    I387.soft.swd := I387.soft.swd and not SW_C1;
  end;

procedure setexponent16 (x: PFPU_REG; y: s32);
  begin
    x^.exp := y;
  end;

function exponent (x: PFPU_REG): u32;
  begin
    Result := ((x^.exp and $7fff) - EXTENDED_Ebias);
  end;

procedure setexponentpos (x: PFPU_REG; y: integer);
  begin
    x^.exp := ((y) + EXTENDED_Ebias) and $7fff;
  end;

end.
