~ubuntu-branches/debian/lenny/fpc/lenny

« back to all changes in this revision

Viewing changes to fpcsrc/compiler/x86_64/nx64mat.pas

  • Committer: Bazaar Package Importer
  • Author(s): Mazen Neifer, Torsten Werner, Mazen Neifer
  • Date: 2008-05-17 17:12:11 UTC
  • mfrom: (3.1.9 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080517171211-9qi33xhd9evfa0kg
Tags: 2.2.0-dfsg1-9
[ Torsten Werner ]
* Add Mazen Neifer to Uploaders field.

[ Mazen Neifer ]
* Moved FPC sources into a version dependent directory from /usr/share/fpcsrc
  to /usr/share/fpcsrc/${FPCVERSION}. This allow installing more than on FPC
  release.
* Fixed far call issue in compiler preventing building huge binearies.
  (closes: #477743)
* Updated building dependencies, recomennded and suggested packages.
* Moved fppkg to fp-utils as it is just a helper tool and is not required by
  compiler.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
{
 
2
    Copyright (c) 1998-2002 by Florian Klaempfl
 
3
 
 
4
    Generate x86-64 assembler for math nodes
 
5
 
 
6
    This program is free software; you can redistribute it and/or modify
 
7
    it under the terms of the GNU General Public License as published by
 
8
    the Free Software Foundation; either version 2 of the License, or
 
9
    (at your option) any later version.
 
10
 
 
11
    This program is distributed in the hope that it will be useful,
 
12
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
    GNU General Public License for more details.
 
15
 
 
16
    You should have received a copy of the GNU General Public License
 
17
    along with this program; if not, write to the Free Software
 
18
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
19
 
 
20
 ****************************************************************************
 
21
}
 
22
unit nx64mat;
 
23
 
 
24
{$i fpcdefs.inc}
 
25
 
 
26
interface
 
27
 
 
28
    uses
 
29
      node,nmat,ncgmat,nx86mat;
 
30
 
 
31
    type
 
32
      tx8664moddivnode = class(tmoddivnode)
 
33
         procedure pass_generate_code;override;
 
34
      end;
 
35
 
 
36
      tx8664shlshrnode = class(tshlshrnode)
 
37
         procedure pass_generate_code;override;
 
38
      end;
 
39
 
 
40
      tx8664unaryminusnode = class(tx86unaryminusnode)
 
41
      end;
 
42
 
 
43
      tx8664notnode = class(tx86notnode)
 
44
      end;
 
45
 
 
46
implementation
 
47
 
 
48
    uses
 
49
      globtype,systems,
 
50
      cutils,verbose,globals,
 
51
      symconst,symdef,aasmbase,aasmtai,aasmdata,defutil,
 
52
      pass_1,pass_2,
 
53
      ncon,
 
54
      cpubase,cpuinfo,
 
55
      cgbase,cgutils,cga,cgobj,cgx86,
 
56
      ncgutil;
 
57
 
 
58
{*****************************************************************************
 
59
                             TX8664MODDIVNODE
 
60
*****************************************************************************}
 
61
 
 
62
    procedure tx8664moddivnode.pass_generate_code;
 
63
      var
 
64
        hreg1,hreg2:Tregister;
 
65
        power:longint;
 
66
        op:Tasmop;
 
67
      begin
 
68
        secondpass(left);
 
69
        if codegenerror then
 
70
          exit;
 
71
        secondpass(right);
 
72
        if codegenerror then
 
73
          exit;
 
74
 
 
75
        { put numerator in register }
 
76
        location_reset(location,LOC_REGISTER,OS_INT);
 
77
        location_force_reg(current_asmdata.CurrAsmList,left.location,OS_INT,false);
 
78
        hreg1:=left.location.register;
 
79
 
 
80
        if (nodetype=divn) and (right.nodetype=ordconstn) and
 
81
           ispowerof2(int64(tordconstnode(right).value),power) then
 
82
          begin
 
83
            { for signed numbers, the numerator must be adjusted before the
 
84
              shift instruction, but not wih unsigned numbers! Otherwise,
 
85
              "Cardinal($ffffffff) div 16" overflows! (JM) }
 
86
            if is_signed(left.resultdef) Then
 
87
              begin
 
88
                  { use a sequence without jumps, saw this in
 
89
                    comp.compilers (JM) }
 
90
                  { no jumps, but more operations }
 
91
                  hreg2:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
 
92
                  emit_reg_reg(A_MOV,S_Q,hreg1,hreg2);
 
93
                  {If the left value is signed, hreg2=$ffffffff, otherwise 0.}
 
94
                  emit_const_reg(A_SAR,S_Q,63,hreg2);
 
95
                  {If signed, hreg2=right value-1, otherwise 0.}
 
96
                  emit_const_reg(A_AND,S_Q,tordconstnode(right).value-1,hreg2);
 
97
                  { add to the left value }
 
98
                  emit_reg_reg(A_ADD,S_Q,hreg2,hreg1);
 
99
                  { do the shift }
 
100
                  emit_const_reg(A_SAR,S_Q,power,hreg1);
 
101
              end
 
102
            else
 
103
              emit_const_reg(A_SHR,S_Q,power,hreg1);
 
104
            location.register:=hreg1;
 
105
          end
 
106
        else
 
107
          begin
 
108
            {Bring denominator to a register.}
 
109
            cg.getcpuregister(current_asmdata.CurrAsmList,NR_RAX);
 
110
            emit_reg_reg(A_MOV,S_Q,hreg1,NR_RAX);
 
111
            cg.getcpuregister(current_asmdata.CurrAsmList,NR_RDX);
 
112
            {Sign extension depends on the left type.}
 
113
            if torddef(left.resultdef).ordtype=u64bit then
 
114
              emit_reg_reg(A_XOR,S_Q,NR_RDX,NR_RDX)
 
115
            else
 
116
              emit_none(A_CQO,S_NO);
 
117
 
 
118
            {Division depends on the right type.}
 
119
            if Torddef(right.resultdef).ordtype=u64bit then
 
120
              op:=A_DIV
 
121
            else
 
122
              op:=A_IDIV;
 
123
 
 
124
            if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
 
125
              emit_ref(op,S_Q,right.location.reference)
 
126
            else if right.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
 
127
              emit_reg(op,S_Q,right.location.register)
 
128
            else
 
129
              begin
 
130
                hreg1:=cg.getintregister(current_asmdata.CurrAsmList,right.location.size);
 
131
                cg.a_load_loc_reg(current_asmdata.CurrAsmList,OS_64,right.location,hreg1);
 
132
                emit_reg(op,S_Q,hreg1);
 
133
              end;
 
134
 
 
135
            { Copy the result into a new register. Release RAX & RDX.}
 
136
            cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_RDX);
 
137
            cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_RAX);
 
138
            location.register:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
 
139
            if nodetype=divn then
 
140
              cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,NR_RAX,location.register)
 
141
            else
 
142
              cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,NR_RDX,location.register);
 
143
          end;
 
144
      end;
 
145
 
 
146
 
 
147
{*****************************************************************************
 
148
                             TX8664SHLRSHRNODE
 
149
*****************************************************************************}
 
150
 
 
151
 
 
152
    procedure tx8664shlshrnode.pass_generate_code;
 
153
      var
 
154
        op : Tasmop;
 
155
        opsize : tcgsize;
 
156
        mask : aint;
 
157
      begin
 
158
        secondpass(left);
 
159
        secondpass(right);
 
160
 
 
161
        { determine operator }
 
162
        if nodetype=shln then
 
163
          op:=A_SHL
 
164
        else
 
165
          op:=A_SHR;
 
166
 
 
167
        { special treatment of 32bit values for backwards compatibility }
 
168
        { mul optimizations require to keep the sign (FK) }
 
169
        if left.resultdef.size<=4 then
 
170
          begin
 
171
            if is_signed(left.resultdef) then
 
172
              opsize:=OS_S32
 
173
            else
 
174
              opsize:=OS_32;
 
175
            mask:=31;
 
176
          end
 
177
        else
 
178
          begin
 
179
            if is_signed(left.resultdef) then
 
180
              opsize:=OS_S64
 
181
            else
 
182
              opsize:=OS_64;
 
183
            mask:=63;
 
184
          end;
 
185
 
 
186
        { load left operators in a register }
 
187
        location_copy(location,left.location);
 
188
        location_force_reg(current_asmdata.CurrAsmList,location,opsize,false);
 
189
 
 
190
        { shifting by a constant directly coded: }
 
191
        if (right.nodetype=ordconstn) then
 
192
          emit_const_reg(op,tcgsize2opsize[opsize],tordconstnode(right).value and mask,location.register)
 
193
        else
 
194
          begin
 
195
            { load right operators in a RCX }
 
196
            cg.getcpuregister(current_asmdata.CurrAsmList,NR_RCX);
 
197
            cg.a_load_loc_reg(current_asmdata.CurrAsmList,OS_INT,right.location,NR_RCX);
 
198
 
 
199
            { right operand is in ECX }
 
200
            cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_RCX);
 
201
            emit_reg_reg(op,tcgsize2opsize[opsize],NR_CL,location.register);
 
202
          end;
 
203
      end;
 
204
 
 
205
 
 
206
begin
 
207
   cunaryminusnode:=tx8664unaryminusnode;
 
208
   cmoddivnode:=tx8664moddivnode;
 
209
   cshlshrnode:=tx8664shlshrnode;
 
210
   cnotnode:=tx8664notnode;
 
211
end.