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

« back to all changes in this revision

Viewing changes to fpcsrc/compiler/arm/cgcpu.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
 
 
3
    Copyright (c) 2003 by Florian Klaempfl
 
4
    Member of the Free Pascal development team
 
5
 
 
6
    This unit implements the code generator for the ARM
 
7
 
 
8
    This program is free software; you can redistribute it and/or modify
 
9
    it under the terms of the GNU General Public License as published by
 
10
    the Free Software Foundation; either version 2 of the License, or
 
11
    (at your option) any later version.
 
12
 
 
13
    This program is distributed in the hope that it will be useful,
 
14
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
    GNU General Public License for more details.
 
17
 
 
18
    You should have received a copy of the GNU General Public License
 
19
    along with this program; if not, write to the Free Software
 
20
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
21
 
 
22
 ****************************************************************************
 
23
}
 
24
unit cgcpu;
 
25
 
 
26
{$i fpcdefs.inc}
 
27
 
 
28
  interface
 
29
 
 
30
    uses
 
31
       globtype,symtype,symdef,
 
32
       cgbase,cgutils,cgobj,
 
33
       aasmbase,aasmcpu,aasmtai,aasmdata,
 
34
       parabase,
 
35
       cpubase,cpuinfo,node,cg64f32,rgcpu;
 
36
 
 
37
 
 
38
    type
 
39
      tcgarm = class(tcg)
 
40
        { true, if the next arithmetic operation should modify the flags }
 
41
        cgsetflags : boolean;
 
42
        procedure init_register_allocators;override;
 
43
        procedure done_register_allocators;override;
 
44
 
 
45
        procedure a_param_const(list : TAsmList;size : tcgsize;a : aint;const paraloc : TCGPara);override;
 
46
        procedure a_param_ref(list : TAsmList;size : tcgsize;const r : treference;const paraloc : TCGPara);override;
 
47
        procedure a_paramaddr_ref(list : TAsmList;const r : treference;const paraloc : TCGPara);override;
 
48
 
 
49
        procedure a_call_name(list : TAsmList;const s : string);override;
 
50
        procedure a_call_reg(list : TAsmList;reg: tregister);override;
 
51
        procedure a_call_ref(list : TAsmList;ref: treference);override;
 
52
 
 
53
        procedure a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: aint; reg: TRegister); override;
 
54
        procedure a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister); override;
 
55
 
 
56
        procedure a_op_const_reg_reg(list: TAsmList; op: TOpCg;
 
57
          size: tcgsize; a: aint; src, dst: tregister); override;
 
58
        procedure a_op_reg_reg_reg(list: TAsmList; op: TOpCg;
 
59
          size: tcgsize; src1, src2, dst: tregister); override;
 
60
        procedure a_op_const_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; a: aint; src, dst: tregister;setflags : boolean;var ovloc : tlocation);override;
 
61
        procedure a_op_reg_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; src1, src2, dst: tregister;setflags : boolean;var ovloc : tlocation);override;
 
62
 
 
63
        { move instructions }
 
64
        procedure a_load_const_reg(list : TAsmList; size: tcgsize; a : aint;reg : tregister);override;
 
65
        procedure a_load_reg_ref(list : TAsmList; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);override;
 
66
        procedure a_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister);override;
 
67
        procedure a_load_reg_reg(list : TAsmList; fromsize, tosize : tcgsize;reg1,reg2 : tregister);override;
 
68
        function a_internal_load_reg_ref(list : TAsmList; fromsize, tosize: tcgsize; reg : tregister;const ref : treference):treference;
 
69
        function a_internal_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister):treference;
 
70
 
 
71
        { fpu move instructions }
 
72
        procedure a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister); override;
 
73
        procedure a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister); override;
 
74
        procedure a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference); override;
 
75
 
 
76
        procedure a_paramfpu_ref(list : TAsmList;size : tcgsize;const ref : treference;const paraloc : TCGPara);override;
 
77
        {  comparison operations }
 
78
        procedure a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : aint;reg : tregister;
 
79
          l : tasmlabel);override;
 
80
        procedure a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel); override;
 
81
 
 
82
        procedure a_jmp_name(list : TAsmList;const s : string); override;
 
83
        procedure a_jmp_always(list : TAsmList;l: tasmlabel); override;
 
84
        procedure a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel); override;
 
85
 
 
86
        procedure g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister); override;
 
87
 
 
88
        procedure g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);override;
 
89
        procedure g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean); override;
 
90
 
 
91
        procedure a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);override;
 
92
 
 
93
        procedure g_concatcopy(list : TAsmList;const source,dest : treference;len : aint);override;
 
94
        procedure g_concatcopy_unaligned(list : TAsmList;const source,dest : treference;len : aint);override;
 
95
        procedure g_concatcopy_move(list : TAsmList;const source,dest : treference;len : aint);
 
96
        procedure g_concatcopy_internal(list : TAsmList;const source,dest : treference;len : aint;aligned : boolean);
 
97
 
 
98
        procedure g_overflowcheck(list: TAsmList; const l: tlocation; def: tdef); override;
 
99
        procedure g_overflowCheck_loc(List:TAsmList;const Loc:TLocation;def:TDef;ovloc : tlocation);override;
 
100
 
 
101
        procedure g_save_standard_registers(list : TAsmList);override;
 
102
        procedure g_restore_standard_registers(list : TAsmList);override;
 
103
 
 
104
        procedure a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
 
105
        procedure fixref(list : TAsmList;var ref : treference);
 
106
        function handle_load_store(list:TAsmList;op: tasmop;oppostfix : toppostfix;reg:tregister;ref: treference):treference;
 
107
 
 
108
        procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
 
109
      end;
 
110
 
 
111
      tcg64farm = class(tcg64f32)
 
112
        procedure a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);override;
 
113
        procedure a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);override;
 
114
        procedure a_op64_const_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64);override;
 
115
        procedure a_op64_reg_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64);override;
 
116
        procedure a_op64_const_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64;setflags : boolean;var ovloc : tlocation);override;
 
117
        procedure a_op64_reg_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64;setflags : boolean;var ovloc : tlocation);override;
 
118
      end;
 
119
 
 
120
    const
 
121
      OpCmp2AsmCond : Array[topcmp] of TAsmCond = (C_NONE,C_EQ,C_GT,
 
122
                           C_LT,C_GE,C_LE,C_NE,C_LS,C_CC,C_CS,C_HI);
 
123
 
 
124
      winstackpagesize = 4096;
 
125
 
 
126
    function get_fpu_postfix(def : tdef) : toppostfix;
 
127
 
 
128
  implementation
 
129
 
 
130
 
 
131
    uses
 
132
       globals,verbose,systems,cutils,
 
133
       fmodule,
 
134
       symconst,symsym,
 
135
       tgobj,
 
136
       procinfo,cpupi,
 
137
       paramgr;
 
138
 
 
139
 
 
140
    function get_fpu_postfix(def : tdef) : toppostfix;
 
141
      begin
 
142
        if def.typ=floatdef then
 
143
          begin
 
144
            case tfloatdef(def).floattype of
 
145
              s32real:
 
146
                result:=PF_S;
 
147
              s64real:
 
148
                result:=PF_D;
 
149
              s80real:
 
150
                result:=PF_E;
 
151
              else
 
152
                internalerror(200401272);
 
153
            end;
 
154
          end
 
155
        else
 
156
          internalerror(200401271);
 
157
      end;
 
158
 
 
159
 
 
160
    procedure tcgarm.init_register_allocators;
 
161
      begin
 
162
        inherited init_register_allocators;
 
163
        { currently, we save R14 always, so we can use it }
 
164
        rg[R_INTREGISTER]:=trgintcpu.create(R_INTREGISTER,R_SUBWHOLE,
 
165
            [RS_R0,RS_R1,RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,
 
166
             RS_R9,RS_R10,RS_R12,RS_R14],first_int_imreg,[]);
 
167
        rg[R_FPUREGISTER]:=trgcpu.create(R_FPUREGISTER,R_SUBNONE,
 
168
            [RS_F0,RS_F1,RS_F2,RS_F3,RS_F4,RS_F5,RS_F6,RS_F7],first_fpu_imreg,[]);
 
169
        rg[R_MMREGISTER]:=trgcpu.create(R_MMREGISTER,R_SUBNONE,
 
170
            [RS_S0,RS_S1,RS_R2,RS_R3,RS_R4,RS_S31],first_mm_imreg,[]);
 
171
      end;
 
172
 
 
173
 
 
174
    procedure tcgarm.done_register_allocators;
 
175
      begin
 
176
        rg[R_INTREGISTER].free;
 
177
        rg[R_FPUREGISTER].free;
 
178
        rg[R_MMREGISTER].free;
 
179
        inherited done_register_allocators;
 
180
      end;
 
181
 
 
182
 
 
183
    procedure tcgarm.a_param_const(list : TAsmList;size : tcgsize;a : aint;const paraloc : TCGPara);
 
184
      var
 
185
        ref: treference;
 
186
      begin
 
187
        paraloc.check_simple_location;
 
188
        case paraloc.location^.loc of
 
189
          LOC_REGISTER,LOC_CREGISTER:
 
190
            a_load_const_reg(list,size,a,paraloc.location^.register);
 
191
          LOC_REFERENCE:
 
192
            begin
 
193
               reference_reset(ref);
 
194
               ref.base:=paraloc.location^.reference.index;
 
195
               ref.offset:=paraloc.location^.reference.offset;
 
196
               a_load_const_ref(list,size,a,ref);
 
197
            end;
 
198
          else
 
199
            internalerror(2002081101);
 
200
        end;
 
201
      end;
 
202
 
 
203
 
 
204
    procedure tcgarm.a_param_ref(list : TAsmList;size : tcgsize;const r : treference;const paraloc : TCGPara);
 
205
      var
 
206
        tmpref, ref: treference;
 
207
        location: pcgparalocation;
 
208
        sizeleft: aint;
 
209
      begin
 
210
        location := paraloc.location;
 
211
        tmpref := r;
 
212
        sizeleft := paraloc.intsize;
 
213
        while assigned(location) do
 
214
          begin
 
215
            case location^.loc of
 
216
              LOC_REGISTER,LOC_CREGISTER:
 
217
                a_load_ref_reg(list,location^.size,location^.size,tmpref,location^.register);
 
218
              LOC_REFERENCE:
 
219
                begin
 
220
                  reference_reset_base(ref,location^.reference.index,location^.reference.offset);
 
221
                  { doubles in softemu mode have a strange order of registers and references }
 
222
                  if location^.size=OS_32 then
 
223
                    g_concatcopy(list,tmpref,ref,4)
 
224
                  else
 
225
                    begin
 
226
                      g_concatcopy(list,tmpref,ref,sizeleft);
 
227
                      if assigned(location^.next) then
 
228
                        internalerror(2005010710);
 
229
                    end;
 
230
                end;
 
231
              LOC_FPUREGISTER,LOC_CFPUREGISTER:
 
232
                case location^.size of
 
233
                   OS_F32, OS_F64:
 
234
                     a_loadfpu_ref_reg(list,location^.size,location^.size,tmpref,location^.register);
 
235
                   else
 
236
                     internalerror(2002072801);
 
237
                end;
 
238
              LOC_VOID:
 
239
                begin
 
240
                  // nothing to do
 
241
                end;
 
242
              else
 
243
                internalerror(2002081103);
 
244
            end;
 
245
            inc(tmpref.offset,tcgsize2size[location^.size]);
 
246
            dec(sizeleft,tcgsize2size[location^.size]);
 
247
            location := location^.next;
 
248
          end;
 
249
      end;
 
250
 
 
251
 
 
252
    procedure tcgarm.a_paramaddr_ref(list : TAsmList;const r : treference;const paraloc : TCGPara);
 
253
      var
 
254
        ref: treference;
 
255
        tmpreg: tregister;
 
256
      begin
 
257
        paraloc.check_simple_location;
 
258
        case paraloc.location^.loc of
 
259
          LOC_REGISTER,LOC_CREGISTER:
 
260
            a_loadaddr_ref_reg(list,r,paraloc.location^.register);
 
261
          LOC_REFERENCE:
 
262
            begin
 
263
              reference_reset(ref);
 
264
              ref.base := paraloc.location^.reference.index;
 
265
              ref.offset := paraloc.location^.reference.offset;
 
266
              tmpreg := getintregister(list,OS_ADDR);
 
267
              a_loadaddr_ref_reg(list,r,tmpreg);
 
268
              a_load_reg_ref(list,OS_ADDR,OS_ADDR,tmpreg,ref);
 
269
            end;
 
270
          else
 
271
            internalerror(2002080701);
 
272
        end;
 
273
      end;
 
274
 
 
275
 
 
276
    procedure tcgarm.a_call_name(list : TAsmList;const s : string);
 
277
      begin
 
278
        list.concat(taicpu.op_sym(A_BL,current_asmdata.RefAsmSymbol(s)));
 
279
{
 
280
        the compiler does not properly set this flag anymore in pass 1, and
 
281
        for now we only need it after pass 2 (I hope) (JM)
 
282
          if not(pi_do_call in current_procinfo.flags) then
 
283
            internalerror(2003060703);
 
284
}
 
285
        include(current_procinfo.flags,pi_do_call);
 
286
      end;
 
287
 
 
288
 
 
289
    procedure tcgarm.a_call_reg(list : TAsmList;reg: tregister);
 
290
      begin
 
291
        list.concat(taicpu.op_reg_reg(A_MOV,NR_R14,NR_PC));
 
292
        list.concat(taicpu.op_reg_reg(A_MOV,NR_PC,reg));
 
293
{
 
294
        the compiler does not properly set this flag anymore in pass 1, and
 
295
        for now we only need it after pass 2 (I hope) (JM)
 
296
          if not(pi_do_call in current_procinfo.flags) then
 
297
            internalerror(2003060703);
 
298
}
 
299
        include(current_procinfo.flags,pi_do_call);
 
300
      end;
 
301
 
 
302
 
 
303
    procedure tcgarm.a_call_ref(list : TAsmList;ref: treference);
 
304
      begin
 
305
        a_reg_alloc(list,NR_R12);
 
306
        a_load_ref_reg(list,OS_ADDR,OS_ADDR,ref,NR_R12);
 
307
        list.concat(taicpu.op_reg_reg(A_MOV,NR_R14,NR_PC));
 
308
        list.concat(taicpu.op_reg_reg(A_MOV,NR_PC,NR_R12));
 
309
        a_reg_dealloc(list,NR_R12);
 
310
        include(current_procinfo.flags,pi_do_call);
 
311
      end;
 
312
 
 
313
 
 
314
     procedure tcgarm.a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: aint; reg: TRegister);
 
315
       begin
 
316
          a_op_const_reg_reg(list,op,size,a,reg,reg);
 
317
       end;
 
318
 
 
319
 
 
320
     procedure tcgarm.a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister);
 
321
       begin
 
322
         case op of
 
323
           OP_NEG:
 
324
             list.concat(taicpu.op_reg_reg_const(A_RSB,dst,src,0));
 
325
           OP_NOT:
 
326
             begin
 
327
               list.concat(taicpu.op_reg_reg(A_MVN,dst,src));
 
328
               case size of
 
329
                 OS_8 :
 
330
                   a_op_const_reg_reg(list,OP_AND,OS_INT,$ff,dst,dst);
 
331
                 OS_16 :
 
332
                   a_op_const_reg_reg(list,OP_AND,OS_INT,$ffff,dst,dst);
 
333
               end;
 
334
             end
 
335
           else
 
336
             a_op_reg_reg_reg(list,op,OS_32,src,dst,dst);
 
337
         end;
 
338
       end;
 
339
 
 
340
 
 
341
    const
 
342
      op_reg_reg_opcg2asmop: array[TOpCG] of tasmop =
 
343
        (A_NONE,A_MOV,A_ADD,A_AND,A_NONE,A_NONE,A_MUL,A_MUL,A_NONE,A_NONE,A_ORR,
 
344
         A_NONE,A_NONE,A_NONE,A_SUB,A_EOR);
 
345
 
 
346
 
 
347
    procedure tcgarm.a_op_const_reg_reg(list: TAsmList; op: TOpCg;
 
348
      size: tcgsize; a: aint; src, dst: tregister);
 
349
      var
 
350
        ovloc : tlocation;
 
351
      begin
 
352
        a_op_const_reg_reg_checkoverflow(list,op,size,a,src,dst,false,ovloc);
 
353
      end;
 
354
 
 
355
 
 
356
    procedure tcgarm.a_op_reg_reg_reg(list: TAsmList; op: TOpCg;
 
357
      size: tcgsize; src1, src2, dst: tregister);
 
358
      var
 
359
        ovloc : tlocation;
 
360
      begin
 
361
        a_op_reg_reg_reg_checkoverflow(list,op,size,src1,src2,dst,false,ovloc);
 
362
      end;
 
363
 
 
364
 
 
365
    procedure tcgarm.a_op_const_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; a: aint; src, dst: tregister;setflags : boolean;var ovloc : tlocation);
 
366
      var
 
367
        shift : byte;
 
368
        tmpreg : tregister;
 
369
        so : tshifterop;
 
370
        l1 : longint;
 
371
      begin
 
372
        ovloc.loc:=LOC_VOID;
 
373
        if is_shifter_const(-a,shift) then
 
374
          case op of
 
375
            OP_ADD:
 
376
              begin
 
377
                op:=OP_SUB;
 
378
                a:=aint(dword(-a));
 
379
              end;
 
380
            OP_SUB:
 
381
              begin
 
382
                op:=OP_ADD;
 
383
                a:=aint(dword(-a));
 
384
              end
 
385
          end;
 
386
 
 
387
        if is_shifter_const(a,shift) and not(op in [OP_IMUL,OP_MUL]) then
 
388
          case op of
 
389
            OP_NEG,OP_NOT,
 
390
            OP_DIV,OP_IDIV:
 
391
              internalerror(200308281);
 
392
            OP_SHL:
 
393
              begin
 
394
                if a>32 then
 
395
                  internalerror(200308294);
 
396
                if a<>0 then
 
397
                  begin
 
398
                    shifterop_reset(so);
 
399
                    so.shiftmode:=SM_LSL;
 
400
                    so.shiftimm:=a;
 
401
                    list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src,so));
 
402
                  end
 
403
                else
 
404
                 list.concat(taicpu.op_reg_reg(A_MOV,dst,src));
 
405
              end;
 
406
            OP_SHR:
 
407
              begin
 
408
                if a>32 then
 
409
                  internalerror(200308292);
 
410
                shifterop_reset(so);
 
411
                if a<>0 then
 
412
                  begin
 
413
                    so.shiftmode:=SM_LSR;
 
414
                    so.shiftimm:=a;
 
415
                    list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src,so));
 
416
                  end
 
417
                else
 
418
                 list.concat(taicpu.op_reg_reg(A_MOV,dst,src));
 
419
              end;
 
420
            OP_SAR:
 
421
              begin
 
422
                if a>32 then
 
423
                  internalerror(200308295);
 
424
                if a<>0 then
 
425
                  begin
 
426
                    shifterop_reset(so);
 
427
                    so.shiftmode:=SM_ASR;
 
428
                    so.shiftimm:=a;
 
429
                    list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src,so));
 
430
                  end
 
431
                else
 
432
                 list.concat(taicpu.op_reg_reg(A_MOV,dst,src));
 
433
              end;
 
434
            else
 
435
              list.concat(setoppostfix(
 
436
                  taicpu.op_reg_reg_const(op_reg_reg_opcg2asmop[op],dst,src,a),toppostfix(ord(cgsetflags or setflags)*ord(PF_S))
 
437
              ));
 
438
              if (cgsetflags or setflags) and (size in [OS_8,OS_16,OS_32]) then
 
439
                begin
 
440
                  ovloc.loc:=LOC_FLAGS;
 
441
                  case op of
 
442
                    OP_ADD:
 
443
                      ovloc.resflags:=F_CS;
 
444
                    OP_SUB:
 
445
                      ovloc.resflags:=F_CC;
 
446
                  end;
 
447
                end;
 
448
          end
 
449
        else
 
450
          begin
 
451
            { there could be added some more sophisticated optimizations }
 
452
            if (op in [OP_MUL,OP_IMUL]) and (a=1) then
 
453
              a_load_reg_reg(list,size,size,src,dst)
 
454
            else if (op in [OP_MUL,OP_IMUL]) and (a=0) then
 
455
              a_load_const_reg(list,size,0,dst)
 
456
            else if (op in [OP_IMUL]) and (a=-1) then
 
457
              a_op_reg_reg(list,OP_NEG,size,src,dst)
 
458
            { we do this here instead in the peephole optimizer because
 
459
              it saves us a register }
 
460
            else if (op in [OP_MUL,OP_IMUL]) and ispowerof2(a,l1) and not(cgsetflags or setflags) then
 
461
              a_op_const_reg_reg(list,OP_SHL,size,l1,src,dst)
 
462
            { for example : b=a*5 -> b=a*4+a with add instruction and shl }
 
463
            else if (op in [OP_MUL,OP_IMUL]) and ispowerof2(a-1,l1) and not(cgsetflags or setflags) then
 
464
              begin
 
465
                if l1>32 then{roozbeh does this ever happen?}
 
466
                  internalerror(200308296);
 
467
                shifterop_reset(so);
 
468
                so.shiftmode:=SM_LSL;
 
469
                so.shiftimm:=l1;
 
470
                list.concat(taicpu.op_reg_reg_reg_shifterop(A_ADD,dst,src,src,so));
 
471
              end
 
472
            else
 
473
              begin
 
474
                tmpreg:=getintregister(list,size);
 
475
                a_load_const_reg(list,size,a,tmpreg);
 
476
                a_op_reg_reg_reg_checkoverflow(list,op,size,tmpreg,src,dst,setflags,ovloc);
 
477
              end;
 
478
          end;
 
479
      end;
 
480
 
 
481
 
 
482
    procedure tcgarm.a_op_reg_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; src1, src2, dst: tregister;setflags : boolean;var ovloc : tlocation);
 
483
      var
 
484
        so : tshifterop;
 
485
        tmpreg,overflowreg : tregister;
 
486
        asmop : tasmop;
 
487
      begin
 
488
        ovloc.loc:=LOC_VOID;
 
489
        case op of
 
490
          OP_NEG,OP_NOT,
 
491
          OP_DIV,OP_IDIV:
 
492
            internalerror(200308281);
 
493
          OP_SHL:
 
494
            begin
 
495
              shifterop_reset(so);
 
496
              so.rs:=src1;
 
497
              so.shiftmode:=SM_LSL;
 
498
              list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src2,so));
 
499
            end;
 
500
          OP_SHR:
 
501
            begin
 
502
              shifterop_reset(so);
 
503
              so.rs:=src1;
 
504
              so.shiftmode:=SM_LSR;
 
505
              list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src2,so));
 
506
            end;
 
507
          OP_SAR:
 
508
            begin
 
509
              shifterop_reset(so);
 
510
              so.rs:=src1;
 
511
              so.shiftmode:=SM_ASR;
 
512
              list.concat(taicpu.op_reg_reg_shifterop(A_MOV,dst,src2,so));
 
513
            end;
 
514
          OP_IMUL,
 
515
          OP_MUL:
 
516
            begin
 
517
              if cgsetflags or setflags then
 
518
                begin
 
519
                  overflowreg:=getintregister(list,size);
 
520
                  if op=OP_IMUL then
 
521
                    asmop:=A_SMULL
 
522
                  else
 
523
                    asmop:=A_UMULL;
 
524
                  { the arm doesn't allow that rd and rm are the same }
 
525
                  if dst=src2 then
 
526
                    begin
 
527
                      if dst<>src1 then
 
528
                        list.concat(taicpu.op_reg_reg_reg_reg(asmop,dst,overflowreg,src1,src2))
 
529
                      else
 
530
                        begin
 
531
                          tmpreg:=getintregister(list,size);
 
532
                          a_load_reg_reg(list,size,size,src2,dst);
 
533
                          list.concat(taicpu.op_reg_reg_reg_reg(asmop,dst,overflowreg,tmpreg,src1));
 
534
                        end;
 
535
                    end
 
536
                  else
 
537
                    list.concat(taicpu.op_reg_reg_reg_reg(asmop,dst,overflowreg,src2,src1));
 
538
                  if op=OP_IMUL then
 
539
                    begin
 
540
                      shifterop_reset(so);
 
541
                      so.shiftmode:=SM_ASR;
 
542
                      so.shiftimm:=31;
 
543
                      list.concat(taicpu.op_reg_reg_shifterop(A_CMP,overflowreg,dst,so));
 
544
                    end
 
545
                  else
 
546
                    list.concat(taicpu.op_reg_const(A_CMP,overflowreg,0));
 
547
 
 
548
                   ovloc.loc:=LOC_FLAGS;
 
549
                   ovloc.resflags:=F_NE;
 
550
                end
 
551
              else
 
552
                begin
 
553
                  { the arm doesn't allow that rd and rm are the same }
 
554
                  if dst=src2 then
 
555
                    begin
 
556
                      if dst<>src1 then
 
557
                        list.concat(taicpu.op_reg_reg_reg(A_MUL,dst,src1,src2))
 
558
                      else
 
559
                        begin
 
560
                          tmpreg:=getintregister(list,size);
 
561
                          a_load_reg_reg(list,size,size,src2,dst);
 
562
                          list.concat(taicpu.op_reg_reg_reg(A_MUL,dst,tmpreg,src1));
 
563
                        end;
 
564
                    end
 
565
                  else
 
566
                    list.concat(taicpu.op_reg_reg_reg(A_MUL,dst,src2,src1));
 
567
                end;
 
568
            end;
 
569
          else
 
570
            list.concat(setoppostfix(
 
571
                taicpu.op_reg_reg_reg(op_reg_reg_opcg2asmop[op],dst,src2,src1),toppostfix(ord(cgsetflags or setflags)*ord(PF_S))
 
572
              ));
 
573
        end;
 
574
      end;
 
575
 
 
576
 
 
577
     procedure tcgarm.a_load_const_reg(list : TAsmList; size: tcgsize; a : aint;reg : tregister);
 
578
       var
 
579
          imm_shift : byte;
 
580
          l : tasmlabel;
 
581
          hr : treference;
 
582
       begin
 
583
          if not(size in [OS_8,OS_S8,OS_16,OS_S16,OS_32,OS_S32]) then
 
584
            internalerror(2002090902);
 
585
          if is_shifter_const(a,imm_shift) then
 
586
            list.concat(taicpu.op_reg_const(A_MOV,reg,a))
 
587
          else if is_shifter_const(not(a),imm_shift) then
 
588
            list.concat(taicpu.op_reg_const(A_MVN,reg,not(a)))
 
589
          { loading of constants with mov and orr }
 
590
          {else [if (is_shifter_const(a-byte(a),imm_shift)) then
 
591
            begin
 
592
              }{ roozbeh:why using tmpreg later causes error in compiling of system.pp,and also those other similars}
 
593
              {list.concat(taicpu.op_reg_const(A_MOV,reg,a-byte(a)));
 
594
              list.concat(taicpu.op_reg_reg_const(A_ORR,reg,reg,byte(a)));
 
595
            end
 
596
          else if (is_shifter_const(a-word(a),imm_shift)) and (is_shifter_const(word(a),imm_shift)) then
 
597
            begin
 
598
              list.concat(taicpu.op_reg_const(A_MOV,reg,a-word(a)));
 
599
              list.concat(taicpu.op_reg_reg_const(A_ORR,reg,reg,word(a)));
 
600
            end
 
601
          else if (is_shifter_const(a-(longint(a) shl 8) shr 8,imm_shift)) and (is_shifter_const((longint(a) shl 8) shr 8,imm_shift)) then
 
602
            begin
 
603
              list.concat(taicpu.op_reg_const(A_MOV,reg,a-(longint(a) shl 8)shr 8));
 
604
              list.concat(taicpu.op_reg_reg_const(A_ORR,reg,reg,(longint(a) shl 8)shr 8));
 
605
            end}
 
606
          else
 
607
            begin
 
608
               reference_reset(hr);
 
609
 
 
610
               current_asmdata.getjumplabel(l);
 
611
               cg.a_label(current_procinfo.aktlocaldata,l);
 
612
               hr.symboldata:=current_procinfo.aktlocaldata.last;
 
613
               current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(longint(a)));
 
614
 
 
615
               hr.symbol:=l;
 
616
               list.concat(taicpu.op_reg_ref(A_LDR,reg,hr));
 
617
            end;
 
618
       end;
 
619
 
 
620
 
 
621
    function tcgarm.handle_load_store(list:TAsmList;op: tasmop;oppostfix : toppostfix;reg:tregister;ref: treference):treference;
 
622
      var
 
623
        tmpreg : tregister;
 
624
        tmpref : treference;
 
625
        l : tasmlabel;
 
626
      begin
 
627
        tmpreg:=NR_NO;
 
628
 
 
629
        { Be sure to have a base register }
 
630
        if (ref.base=NR_NO) then
 
631
          begin
 
632
            if ref.shiftmode<>SM_None then
 
633
              internalerror(200308294);
 
634
            ref.base:=ref.index;
 
635
            ref.index:=NR_NO;
 
636
          end;
 
637
 
 
638
        { absolute symbols can't be handled directly, we've to store the symbol reference
 
639
          in the text segment and access it pc relative
 
640
 
 
641
          For now, we assume that references where base or index equals to PC are already
 
642
          relative, all other references are assumed to be absolute and thus they need
 
643
          to be handled extra.
 
644
 
 
645
          A proper solution would be to change refoptions to a set and store the information
 
646
          if the symbol is absolute or relative there.
 
647
        }
 
648
 
 
649
        if (assigned(ref.symbol) and
 
650
            not(is_pc(ref.base)) and
 
651
            not(is_pc(ref.index))
 
652
           ) or
 
653
           { [#xxx] isn't a valid address operand }
 
654
           ((ref.base=NR_NO) and (ref.index=NR_NO)) or
 
655
           (ref.offset<-4095) or
 
656
           (ref.offset>4095) or
 
657
           ((oppostfix in [PF_SB,PF_H,PF_SH]) and
 
658
            ((ref.offset<-255) or
 
659
             (ref.offset>255)
 
660
            )
 
661
           ) or
 
662
           ((op in [A_LDF,A_STF]) and
 
663
            ((ref.offset<-1020) or
 
664
             (ref.offset>1020) or
 
665
             { the usual pc relative symbol handling assumes possible offsets of +/- 4095 }
 
666
             assigned(ref.symbol)
 
667
            )
 
668
           ) then
 
669
          begin
 
670
            reference_reset(tmpref);
 
671
 
 
672
            { load symbol }
 
673
            tmpreg:=getintregister(list,OS_INT);
 
674
            if assigned(ref.symbol) then
 
675
              begin
 
676
                current_asmdata.getjumplabel(l);
 
677
                cg.a_label(current_procinfo.aktlocaldata,l);
 
678
                tmpref.symboldata:=current_procinfo.aktlocaldata.last;
 
679
 
 
680
                current_procinfo.aktlocaldata.concat(tai_const.create_sym_offset(ref.symbol,ref.offset));
 
681
 
 
682
                { load consts entry }
 
683
                tmpref.symbol:=l;
 
684
                tmpref.base:=NR_R15;
 
685
                list.concat(taicpu.op_reg_ref(A_LDR,tmpreg,tmpref));
 
686
 
 
687
                { in case of LDF/STF, we got rid of the NR_R15 }
 
688
                if is_pc(ref.base) then
 
689
                  ref.base:=NR_NO;
 
690
                if is_pc(ref.index) then
 
691
                  ref.index:=NR_NO;
 
692
              end
 
693
            else
 
694
              a_load_const_reg(list,OS_ADDR,ref.offset,tmpreg);
 
695
 
 
696
            if (ref.base<>NR_NO) then
 
697
              begin
 
698
                if ref.index<>NR_NO then
 
699
                  begin
 
700
                    list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
 
701
                    ref.base:=tmpreg;
 
702
                  end
 
703
                else
 
704
                  begin
 
705
                    ref.index:=tmpreg;
 
706
                    ref.shiftimm:=0;
 
707
                    ref.signindex:=1;
 
708
                    ref.shiftmode:=SM_None;
 
709
                  end;
 
710
              end
 
711
            else
 
712
              ref.base:=tmpreg;
 
713
            ref.offset:=0;
 
714
            ref.symbol:=nil;
 
715
          end;
 
716
 
 
717
        if (ref.base<>NR_NO) and (ref.index<>NR_NO) and (ref.offset<>0) then
 
718
          begin
 
719
            if tmpreg<>NR_NO then
 
720
              a_op_const_reg_reg(list,OP_ADD,OS_ADDR,ref.offset,tmpreg,tmpreg)
 
721
            else
 
722
              begin
 
723
                tmpreg:=getintregister(list,OS_ADDR);
 
724
                a_op_const_reg_reg(list,OP_ADD,OS_ADDR,ref.offset,ref.base,tmpreg);
 
725
                ref.base:=tmpreg;
 
726
              end;
 
727
            ref.offset:=0;
 
728
          end;
 
729
 
 
730
        { floating point operations have only limited references
 
731
          we expect here, that a base is already set }
 
732
        if (op in [A_LDF,A_STF]) and (ref.index<>NR_NO) then
 
733
          begin
 
734
            if ref.shiftmode<>SM_none then
 
735
              internalerror(200309121);
 
736
            if tmpreg<>NR_NO then
 
737
              begin
 
738
                if ref.base=tmpreg then
 
739
                  begin
 
740
                    if ref.signindex<0 then
 
741
                      list.concat(taicpu.op_reg_reg_reg(A_SUB,tmpreg,tmpreg,ref.index))
 
742
                    else
 
743
                      list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,tmpreg,ref.index));
 
744
                    ref.index:=NR_NO;
 
745
                  end
 
746
                else
 
747
                  begin
 
748
                    if ref.index<>tmpreg then
 
749
                      internalerror(200403161);
 
750
                    if ref.signindex<0 then
 
751
                      list.concat(taicpu.op_reg_reg_reg(A_SUB,tmpreg,ref.base,tmpreg))
 
752
                    else
 
753
                      list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
 
754
                    ref.base:=tmpreg;
 
755
                    ref.index:=NR_NO;
 
756
                  end;
 
757
              end
 
758
            else
 
759
              begin
 
760
                tmpreg:=getintregister(list,OS_ADDR);
 
761
                list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,ref.index));
 
762
                ref.base:=tmpreg;
 
763
                ref.index:=NR_NO;
 
764
              end;
 
765
          end;
 
766
        list.concat(setoppostfix(taicpu.op_reg_ref(op,reg,ref),oppostfix));
 
767
        Result := ref;
 
768
      end;
 
769
 
 
770
 
 
771
     procedure tcgarm.a_load_reg_ref(list : TAsmList; fromsize, tosize: tcgsize; reg : tregister;const ref : treference);
 
772
       var
 
773
         oppostfix:toppostfix;
 
774
         usedtmpref: treference;
 
775
         tmpreg : tregister;
 
776
         so : tshifterop;
 
777
       begin
 
778
         case ToSize of
 
779
           { signed integer registers }
 
780
           OS_8,
 
781
           OS_S8:
 
782
             oppostfix:=PF_B;
 
783
           OS_16,
 
784
           OS_S16:
 
785
             oppostfix:=PF_H;
 
786
           OS_32,
 
787
           OS_S32:
 
788
             oppostfix:=PF_None;
 
789
           else
 
790
             InternalError(200308295);
 
791
         end;
 
792
         if ref.alignment<>0 then
 
793
           begin
 
794
             case FromSize of
 
795
               OS_16,OS_S16:
 
796
                 begin
 
797
                   shifterop_reset(so);so.shiftmode:=SM_LSR;so.shiftimm:=8;
 
798
                   tmpreg:=getintregister(list,OS_INT);
 
799
                   usedtmpref:=a_internal_load_reg_ref(list,OS_8,OS_8,reg,Ref);
 
800
                   inc(usedtmpref.offset);
 
801
                   list.concat(taicpu.op_reg_reg_shifterop(A_MOV,tmpreg,reg,so));
 
802
                   a_internal_load_reg_ref(list,OS_8,OS_8,tmpreg,usedtmpref);
 
803
                 end;
 
804
               OS_32,OS_S32:
 
805
                 begin
 
806
                   shifterop_reset(so);so.shiftmode:=SM_LSR;so.shiftimm:=8;
 
807
                   tmpreg:=getintregister(list,OS_INT);
 
808
                   usedtmpref:=a_internal_load_reg_ref(list,OS_8,OS_8,reg,Ref);
 
809
                   list.concat(taicpu.op_reg_reg_shifterop(A_MOV,tmpreg,reg,so));
 
810
                   inc(usedtmpref.offset);
 
811
                   a_internal_load_reg_ref(list,OS_8,OS_8,tmpreg,usedtmpref);
 
812
                   list.concat(taicpu.op_reg_reg_shifterop(A_MOV,tmpreg,tmpreg,so));
 
813
                   inc(usedtmpref.offset);
 
814
                   a_internal_load_reg_ref(list,OS_8,OS_8,tmpreg,usedtmpref);
 
815
                   list.concat(taicpu.op_reg_reg_shifterop(A_MOV,tmpreg,tmpreg,so));
 
816
                   inc(usedtmpref.offset);
 
817
                   a_internal_load_reg_ref(list,OS_8,OS_8,tmpreg,usedtmpref);
 
818
                 end
 
819
               else
 
820
                 handle_load_store(list,A_STR,oppostfix,reg,ref);
 
821
             end;
 
822
           end
 
823
         else
 
824
           handle_load_store(list,A_STR,oppostfix,reg,ref);
 
825
       end;
 
826
 
 
827
 
 
828
     procedure tcgarm.a_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister);
 
829
       var
 
830
         oppostfix:toppostfix;
 
831
         usedtmpref: treference;
 
832
         tmpreg,tmpreg2,tmpreg3 : tregister;
 
833
         so : tshifterop;
 
834
       begin
 
835
         case FromSize of
 
836
           { signed integer registers }
 
837
           OS_8:
 
838
             oppostfix:=PF_B;
 
839
           OS_S8:
 
840
             oppostfix:=PF_SB;
 
841
           OS_16:
 
842
             oppostfix:=PF_H;
 
843
           OS_S16:
 
844
             oppostfix:=PF_SH;
 
845
           OS_32,
 
846
           OS_S32:
 
847
             oppostfix:=PF_None;
 
848
           else
 
849
             InternalError(200308297);
 
850
         end;
 
851
         if Ref.alignment<>0 then
 
852
           begin
 
853
             case FromSize of
 
854
               OS_16,OS_S16:
 
855
                 begin
 
856
                   { only complicated references need an extra loadaddr }
 
857
                   if assigned(ref.symbol) or
 
858
                     (ref.index<>NR_NO) or
 
859
                     (ref.offset<-4095) or
 
860
                     (ref.offset>4094) or
 
861
                     { sometimes the compiler reused registers }
 
862
                     (reg=ref.index) or
 
863
                     (reg=ref.base) then
 
864
                     begin
 
865
                       tmpreg3:=getintregister(list,OS_INT);
 
866
                       a_loadaddr_ref_reg(list,ref,tmpreg3);
 
867
                       reference_reset_base(usedtmpref,tmpreg3,0);
 
868
                     end
 
869
                   else
 
870
                     usedtmpref:=ref;
 
871
 
 
872
                   shifterop_reset(so);so.shiftmode:=SM_LSL;so.shiftimm:=8;
 
873
                   tmpreg:=getintregister(list,OS_INT);
 
874
                   a_internal_load_ref_reg(list,OS_8,OS_8,usedtmpref,tmpreg);
 
875
                   inc(usedtmpref.offset);
 
876
                   tmpreg2:=getintregister(list,OS_INT);
 
877
                   if FromSize=OS_16 then
 
878
                     a_internal_load_ref_reg(list,OS_8,OS_8,usedtmpref,tmpreg2)
 
879
                   else
 
880
                     a_internal_load_ref_reg(list,OS_S8,OS_S8,usedtmpref,tmpreg2);
 
881
                   list.concat(taicpu.op_reg_reg_reg_shifterop(A_ORR,reg,tmpreg,tmpreg2,so));
 
882
                 end;
 
883
               OS_32,OS_S32:
 
884
                 begin
 
885
                   tmpreg:=getintregister(list,OS_INT);
 
886
                   tmpreg2:=getintregister(list,OS_INT);
 
887
 
 
888
                   { only complicated references need an extra loadaddr }
 
889
                   if assigned(ref.symbol) or
 
890
                     (ref.index<>NR_NO) or
 
891
                     (ref.offset<-4095) or
 
892
                     (ref.offset>4092) or
 
893
                     { sometimes the compiler reused registers }
 
894
                     (reg=ref.index) or
 
895
                     (reg=ref.base) then
 
896
                     begin
 
897
                       tmpreg3:=getintregister(list,OS_INT);
 
898
                       a_loadaddr_ref_reg(list,ref,tmpreg3);
 
899
                       reference_reset_base(usedtmpref,tmpreg3,0);
 
900
                     end
 
901
                   else
 
902
                     usedtmpref:=ref;
 
903
 
 
904
                   shifterop_reset(so);so.shiftmode:=SM_LSL;so.shiftimm:=8;
 
905
                   a_internal_load_ref_reg(list,OS_8,OS_8,usedtmpref,reg);
 
906
                   inc(usedtmpref.offset);
 
907
                   a_internal_load_ref_reg(list,OS_8,OS_8,usedtmpref,tmpreg);
 
908
                   list.concat(taicpu.op_reg_reg_reg_shifterop(A_ORR,tmpreg2,reg,tmpreg,so));
 
909
                   inc(usedtmpref.offset);
 
910
                   a_internal_load_ref_reg(list,OS_8,OS_8,usedtmpref,reg);
 
911
                   so.shiftimm:=16;
 
912
                   list.concat(taicpu.op_reg_reg_reg_shifterop(A_ORR,tmpreg,tmpreg2,reg,so));
 
913
                   inc(usedtmpref.offset);
 
914
                   a_internal_load_ref_reg(list,OS_8,OS_8,usedtmpref,tmpreg2);
 
915
                   so.shiftimm:=24;
 
916
                   list.concat(taicpu.op_reg_reg_reg_shifterop(A_ORR,reg,tmpreg,tmpreg2,so));
 
917
                 end
 
918
               else
 
919
                 handle_load_store(list,A_LDR,oppostfix,reg,ref);
 
920
             end;
 
921
           end
 
922
         else
 
923
           handle_load_store(list,A_LDR,oppostfix,reg,ref);
 
924
       end;
 
925
 
 
926
 
 
927
     function tcgarm.a_internal_load_reg_ref(list : TAsmList; fromsize, tosize: tcgsize; reg : tregister;const ref : treference):treference;
 
928
       var
 
929
         oppostfix:toppostfix;
 
930
       begin
 
931
         case ToSize of
 
932
           { signed integer registers }
 
933
           OS_8,
 
934
           OS_S8:
 
935
             oppostfix:=PF_B;
 
936
           OS_16,
 
937
           OS_S16:
 
938
             oppostfix:=PF_H;
 
939
           OS_32,
 
940
           OS_S32:
 
941
             oppostfix:=PF_None;
 
942
           else
 
943
             InternalError(2003082910);
 
944
         end;
 
945
         result:=handle_load_store(list,A_STR,oppostfix,reg,ref);
 
946
       end;
 
947
 
 
948
 
 
949
     function tcgarm.a_internal_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister):treference;
 
950
       var
 
951
         oppostfix:toppostfix;
 
952
       begin
 
953
         case FromSize of
 
954
           { signed integer registers }
 
955
           OS_8:
 
956
             oppostfix:=PF_B;
 
957
           OS_S8:
 
958
             oppostfix:=PF_SB;
 
959
           OS_16:
 
960
             oppostfix:=PF_H;
 
961
           OS_S16:
 
962
             oppostfix:=PF_SH;
 
963
           OS_32,
 
964
           OS_S32:
 
965
             oppostfix:=PF_None;
 
966
           else
 
967
             InternalError(200308291);
 
968
         end;
 
969
         result:=handle_load_store(list,A_LDR,oppostfix,reg,ref);
 
970
       end;
 
971
 
 
972
     procedure tcgarm.a_load_reg_reg(list : TAsmList; fromsize, tosize : tcgsize;reg1,reg2 : tregister);
 
973
       var
 
974
         so : tshifterop;
 
975
         conv_done: boolean;
 
976
 
 
977
       procedure do_shift(shiftmode : tshiftmode; shiftimm : byte; reg : tregister);
 
978
         begin
 
979
           so.shiftmode:=shiftmode;
 
980
           so.shiftimm:=shiftimm;
 
981
           list.concat(taicpu.op_reg_reg_shifterop(A_MOV,reg2,reg,so));
 
982
         end;
 
983
 
 
984
       function do_conv(size : tcgsize) : boolean;
 
985
         begin
 
986
           result:=true;
 
987
           case size of
 
988
             OS_8:
 
989
               list.concat(taicpu.op_reg_reg_const(A_AND,reg2,reg1,$ff));
 
990
             OS_S8:
 
991
               begin
 
992
                 do_shift(SM_LSL,24,reg1);
 
993
                 do_shift(SM_ASR,24,reg2);
 
994
               end;
 
995
             OS_16,OS_S16:
 
996
               begin
 
997
                 do_shift(SM_LSL,16,reg1);
 
998
                 if size=OS_S16 then
 
999
                   do_shift(SM_ASR,16,reg2)
 
1000
                 else
 
1001
                   do_shift(SM_LSR,16,reg2);
 
1002
               end;
 
1003
             else
 
1004
               result:=false;
 
1005
           end;
 
1006
           conv_done:=result;
 
1007
         end;
 
1008
 
 
1009
       var
 
1010
         instr: taicpu;
 
1011
       begin
 
1012
         conv_done:=false;
 
1013
         if tcgsize2size[tosize]<>tcgsize2size[fromsize] then
 
1014
           begin
 
1015
             shifterop_reset(so);
 
1016
             if not do_conv(tosize) then
 
1017
               if tosize in [OS_32,OS_S32] then
 
1018
                 do_conv(fromsize)
 
1019
               else
 
1020
                 internalerror(2002090901);
 
1021
           end;
 
1022
         if not conv_done and (reg1<>reg2) then
 
1023
           begin
 
1024
             { same size, only a register mov required }
 
1025
             instr:=taicpu.op_reg_reg(A_MOV,reg2,reg1);
 
1026
             list.Concat(instr);
 
1027
             { Notify the register allocator that we have written a move instruction so
 
1028
               it can try to eliminate it. }
 
1029
             add_move_instruction(instr);
 
1030
           end;
 
1031
       end;
 
1032
 
 
1033
 
 
1034
    procedure tcgarm.a_paramfpu_ref(list : TAsmList;size : tcgsize;const ref : treference;const paraloc : TCGPara);
 
1035
      var
 
1036
         href,href2 : treference;
 
1037
         hloc : pcgparalocation;
 
1038
      begin
 
1039
        href:=ref;
 
1040
        hloc:=paraloc.location;
 
1041
        while assigned(hloc) do
 
1042
          begin
 
1043
            case hloc^.loc of
 
1044
              LOC_FPUREGISTER,LOC_CFPUREGISTER:
 
1045
                a_loadfpu_ref_reg(list,size,size,ref,hloc^.register);
 
1046
              LOC_REGISTER :
 
1047
                case hloc^.size of
 
1048
                  OS_F32:
 
1049
                    a_load_ref_reg(list,OS_32,OS_32,href,hloc^.register);
 
1050
                  OS_64,
 
1051
                  OS_F64:
 
1052
                    cg64.a_param64_ref(list,href,paraloc);
 
1053
                  else
 
1054
                    a_load_ref_reg(list,hloc^.size,hloc^.size,href,hloc^.register);
 
1055
                end;
 
1056
              LOC_REFERENCE :
 
1057
                begin
 
1058
                  reference_reset_base(href2,hloc^.reference.index,hloc^.reference.offset);
 
1059
                  { concatcopy should choose the best way to copy the data }
 
1060
                  g_concatcopy(list,href,href2,tcgsize2size[size]);
 
1061
                end;
 
1062
              else
 
1063
                internalerror(200408241);
 
1064
           end;
 
1065
           inc(href.offset,tcgsize2size[hloc^.size]);
 
1066
           hloc:=hloc^.next;
 
1067
         end;
 
1068
      end;
 
1069
 
 
1070
 
 
1071
     procedure tcgarm.a_loadfpu_reg_reg(list: TAsmList; fromsize,tosize: tcgsize; reg1, reg2: tregister);
 
1072
       begin
 
1073
         list.concat(setoppostfix(taicpu.op_reg_reg(A_MVF,reg2,reg1),cgsize2fpuoppostfix[tosize]));
 
1074
       end;
 
1075
 
 
1076
 
 
1077
     procedure tcgarm.a_loadfpu_ref_reg(list: TAsmList; fromsize,tosize: tcgsize; const ref: treference; reg: tregister);
 
1078
       var
 
1079
         oppostfix:toppostfix;
 
1080
       begin
 
1081
         case tosize of
 
1082
           OS_32,
 
1083
           OS_F32:
 
1084
             oppostfix:=PF_S;
 
1085
           OS_64,
 
1086
           OS_F64:
 
1087
             oppostfix:=PF_D;
 
1088
           OS_F80:
 
1089
             oppostfix:=PF_E;
 
1090
           else
 
1091
             InternalError(200309021);
 
1092
         end;
 
1093
         handle_load_store(list,A_LDF,oppostfix,reg,ref);
 
1094
       end;
 
1095
 
 
1096
 
 
1097
     procedure tcgarm.a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference);
 
1098
       var
 
1099
         oppostfix:toppostfix;
 
1100
       begin
 
1101
         case tosize of
 
1102
           OS_F32:
 
1103
             oppostfix:=PF_S;
 
1104
           OS_F64:
 
1105
             oppostfix:=PF_D;
 
1106
           OS_F80:
 
1107
             oppostfix:=PF_E;
 
1108
           else
 
1109
             InternalError(200309022);
 
1110
         end;
 
1111
         handle_load_store(list,A_STF,oppostfix,reg,ref);
 
1112
       end;
 
1113
 
 
1114
 
 
1115
    {  comparison operations }
 
1116
    procedure tcgarm.a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : aint;reg : tregister;
 
1117
      l : tasmlabel);
 
1118
      var
 
1119
        tmpreg : tregister;
 
1120
        b : byte;
 
1121
      begin
 
1122
        if is_shifter_const(a,b) then
 
1123
          list.concat(taicpu.op_reg_const(A_CMP,reg,a))
 
1124
        { CMN reg,0 and CMN reg,$80000000 are different from CMP reg,$ffffffff
 
1125
          and CMP reg,$7fffffff regarding the flags according to the ARM manual }
 
1126
        else if (a<>$7fffffff) and (a<>-1) and is_shifter_const(-a,b) then
 
1127
          list.concat(taicpu.op_reg_const(A_CMN,reg,-a))
 
1128
        else
 
1129
          begin
 
1130
            tmpreg:=getintregister(list,size);
 
1131
            a_load_const_reg(list,size,a,tmpreg);
 
1132
            list.concat(taicpu.op_reg_reg(A_CMP,reg,tmpreg));
 
1133
          end;
 
1134
        a_jmp_cond(list,cmp_op,l);
 
1135
      end;
 
1136
 
 
1137
 
 
1138
    procedure tcgarm.a_cmp_reg_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel);
 
1139
      begin
 
1140
        list.concat(taicpu.op_reg_reg(A_CMP,reg2,reg1));
 
1141
        a_jmp_cond(list,cmp_op,l);
 
1142
      end;
 
1143
 
 
1144
 
 
1145
    procedure tcgarm.a_jmp_name(list : TAsmList;const s : string);
 
1146
      var
 
1147
        ai : taicpu;
 
1148
      begin
 
1149
        ai:=taicpu.op_sym(A_B,current_asmdata.RefAsmSymbol(s));
 
1150
        ai.is_jmp:=true;
 
1151
        list.concat(ai);
 
1152
      end;
 
1153
 
 
1154
 
 
1155
    procedure tcgarm.a_jmp_always(list : TAsmList;l: tasmlabel);
 
1156
      var
 
1157
        ai : taicpu;
 
1158
      begin
 
1159
        ai:=taicpu.op_sym(A_B,l);
 
1160
        ai.is_jmp:=true;
 
1161
        list.concat(ai);
 
1162
      end;
 
1163
 
 
1164
 
 
1165
    procedure tcgarm.a_jmp_flags(list : TAsmList;const f : TResFlags;l: tasmlabel);
 
1166
      var
 
1167
        ai : taicpu;
 
1168
      begin
 
1169
        ai:=setcondition(taicpu.op_sym(A_B,l),flags_to_cond(f));
 
1170
        ai.is_jmp:=true;
 
1171
        list.concat(ai);
 
1172
      end;
 
1173
 
 
1174
 
 
1175
    procedure tcgarm.g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister);
 
1176
      begin
 
1177
        list.concat(setcondition(taicpu.op_reg_const(A_MOV,reg,1),flags_to_cond(f)));
 
1178
        list.concat(setcondition(taicpu.op_reg_const(A_MOV,reg,0),inverse_cond(flags_to_cond(f))));
 
1179
      end;
 
1180
 
 
1181
 
 
1182
    procedure tcgarm.g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);
 
1183
      var
 
1184
         ref : treference;
 
1185
         shift : byte;
 
1186
         firstfloatreg,lastfloatreg,
 
1187
         r : byte;
 
1188
         regs : tcpuregisterset;
 
1189
      begin
 
1190
        LocalSize:=align(LocalSize,4);
 
1191
        if not(nostackframe) then
 
1192
          begin
 
1193
            firstfloatreg:=RS_NO;
 
1194
            { save floating point registers? }
 
1195
            for r:=RS_F0 to RS_F7 do
 
1196
              if r in rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall) then
 
1197
                begin
 
1198
                  if firstfloatreg=RS_NO then
 
1199
                    firstfloatreg:=r;
 
1200
                  lastfloatreg:=r;
 
1201
                end;
 
1202
            a_reg_alloc(list,NR_STACK_POINTER_REG);
 
1203
            if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
 
1204
              begin
 
1205
                a_reg_alloc(list,NR_FRAME_POINTER_REG);
 
1206
                a_reg_alloc(list,NR_R12);
 
1207
 
 
1208
                list.concat(taicpu.op_reg_reg(A_MOV,NR_R12,NR_STACK_POINTER_REG));
 
1209
              end;
 
1210
            { save int registers }
 
1211
            reference_reset(ref);
 
1212
            ref.index:=NR_STACK_POINTER_REG;
 
1213
            ref.addressmode:=AM_PREINDEXED;
 
1214
            regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
 
1215
            if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
 
1216
              regs:=regs+[RS_R11,RS_R12,RS_R14,RS_R15]
 
1217
            else
 
1218
              if (regs<>[]) or (pi_do_call in current_procinfo.flags) then
 
1219
                include(regs,RS_R14);
 
1220
            if regs<>[] then
 
1221
              list.concat(setoppostfix(taicpu.op_ref_regset(A_STM,ref,regs),PF_FD));
 
1222
 
 
1223
            if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
 
1224
              list.concat(taicpu.op_reg_reg_const(A_SUB,NR_FRAME_POINTER_REG,NR_R12,4));
 
1225
 
 
1226
            { allocate necessary stack size
 
1227
              not necessary according to Yury Sidorov
 
1228
 
 
1229
            { don't use a_op_const_reg_reg here because we don't allow register allocations
 
1230
              in the entry/exit code }
 
1231
           if (target_info.system in [system_arm_wince]) and
 
1232
              (localsize>=winstackpagesize) then
 
1233
             begin
 
1234
               if localsize div winstackpagesize<=5 then
 
1235
                 begin
 
1236
                    if is_shifter_const(localsize,shift) then
 
1237
                      list.concat(Taicpu.op_reg_reg_const(A_SUB,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,localsize))
 
1238
                    else
 
1239
                      begin
 
1240
                        a_load_const_reg(list,OS_ADDR,localsize,NR_R12);
 
1241
                        list.concat(taicpu.op_reg_reg_reg(A_SUB,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,NR_R12));
 
1242
                      end;
 
1243
 
 
1244
                    for i:=1 to localsize div winstackpagesize do
 
1245
                      begin
 
1246
                        if localsize-i*winstackpagesize<4096 then
 
1247
                          reference_reset_base(href,NR_STACK_POINTER_REG,-(localsize-i*winstackpagesize))
 
1248
                        else
 
1249
                          begin
 
1250
                            a_load_const_reg(list,OS_ADDR,-(localsize-i*winstackpagesize),NR_R12);
 
1251
                            reference_reset_base(href,NR_STACK_POINTER_REG,0);
 
1252
                            href.index:=NR_R12;
 
1253
                          end;
 
1254
                        { the data stored doesn't matter }
 
1255
                        list.concat(Taicpu.op_reg_ref(A_STR,NR_R0,href));
 
1256
                      end;
 
1257
                    a_reg_dealloc(list,NR_R12);
 
1258
                    reference_reset_base(href,NR_STACK_POINTER_REG,0);
 
1259
                    { the data stored doesn't matter }
 
1260
                    list.concat(Taicpu.op_reg_ref(A_STR,NR_R0,href));
 
1261
                 end
 
1262
               else
 
1263
                 begin
 
1264
                    current_asmdata.getjumplabel(again);
 
1265
                    list.concat(Taicpu.op_reg_const(A_MOV,NR_R12,localsize div winstackpagesize));
 
1266
                    a_label(list,again);
 
1267
                    { always shifterop }
 
1268
                    list.concat(Taicpu.op_reg_reg_const(A_SUB,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,winstackpagesize));
 
1269
                    reference_reset_base(href,NR_STACK_POINTER_REG,0);
 
1270
                    { the data stored doesn't matter }
 
1271
                    list.concat(Taicpu.op_reg_ref(A_STR,NR_R0,href));
 
1272
                    list.concat(Taicpu.op_reg_reg_const(A_SUB,NR_R12,NR_R12,1));
 
1273
                    a_jmp_cond(list,OC_NE,again);
 
1274
                    if is_shifter_const(localsize mod winstackpagesize,shift) then
 
1275
                      list.concat(Taicpu.op_reg_reg_const(A_SUB,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,localsize mod winstackpagesize))
 
1276
                    else
 
1277
                      begin
 
1278
                        a_load_const_reg(list,OS_ADDR,localsize mod winstackpagesize,NR_R12);
 
1279
                        list.concat(taicpu.op_reg_reg_reg(A_SUB,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,NR_R12));
 
1280
                      end;
 
1281
                    a_reg_dealloc(list,NR_R12);
 
1282
                    reference_reset_base(href,NR_STACK_POINTER_REG,0);
 
1283
                    { the data stored doesn't matter }
 
1284
                    list.concat(Taicpu.op_reg_ref(A_STR,NR_R0,href));
 
1285
                 end
 
1286
             end
 
1287
            else
 
1288
            }
 
1289
            if LocalSize<>0 then
 
1290
              if not(is_shifter_const(localsize,shift)) then
 
1291
                begin
 
1292
                  if current_procinfo.framepointer=NR_STACK_POINTER_REG then
 
1293
                    a_reg_alloc(list,NR_R12);
 
1294
                  a_load_const_reg(list,OS_ADDR,LocalSize,NR_R12);
 
1295
                  list.concat(taicpu.op_reg_reg_reg(A_SUB,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,NR_R12));
 
1296
                  a_reg_dealloc(list,NR_R12);
 
1297
                end
 
1298
              else
 
1299
                begin
 
1300
                  a_reg_dealloc(list,NR_R12);
 
1301
                  list.concat(taicpu.op_reg_reg_const(A_SUB,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,LocalSize));
 
1302
                end;
 
1303
 
 
1304
            if firstfloatreg<>RS_NO then
 
1305
              begin
 
1306
                reference_reset(ref);
 
1307
                if tg.direction*tarmprocinfo(current_procinfo).floatregstart>=1023 then
 
1308
                  begin
 
1309
                    a_load_const_reg(list,OS_ADDR,-tarmprocinfo(current_procinfo).floatregstart,NR_R12);
 
1310
                    list.concat(taicpu.op_reg_reg_reg(A_SUB,NR_R12,current_procinfo.framepointer,NR_R12));
 
1311
                    ref.base:=NR_R12;
 
1312
                  end
 
1313
                else
 
1314
                  begin
 
1315
                    ref.base:=current_procinfo.framepointer;
 
1316
                    ref.offset:=tarmprocinfo(current_procinfo).floatregstart;
 
1317
                  end;
 
1318
                list.concat(taicpu.op_reg_const_ref(A_SFM,newreg(R_FPUREGISTER,firstfloatreg,R_SUBWHOLE),
 
1319
                  lastfloatreg-firstfloatreg+1,ref));
 
1320
              end;
 
1321
          end;
 
1322
      end;
 
1323
 
 
1324
 
 
1325
    procedure tcgarm.g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean);
 
1326
      var
 
1327
         ref : treference;
 
1328
         firstfloatreg,lastfloatreg,
 
1329
         r : byte;
 
1330
         shift : byte;
 
1331
         regs : tcpuregisterset;
 
1332
         LocalSize : longint;
 
1333
      begin
 
1334
        if not(nostackframe) then
 
1335
          begin
 
1336
            { restore floating point register }
 
1337
            firstfloatreg:=RS_NO;
 
1338
            { save floating point registers? }
 
1339
            for r:=RS_F0 to RS_F7 do
 
1340
              if r in rg[R_FPUREGISTER].used_in_proc-paramanager.get_volatile_registers_fpu(pocall_stdcall) then
 
1341
                begin
 
1342
                  if firstfloatreg=RS_NO then
 
1343
                    firstfloatreg:=r;
 
1344
                  lastfloatreg:=r;
 
1345
                end;
 
1346
 
 
1347
            if firstfloatreg<>RS_NO then
 
1348
              begin
 
1349
                reference_reset(ref);
 
1350
                if tg.direction*tarmprocinfo(current_procinfo).floatregstart>=1023 then
 
1351
                  begin
 
1352
                    a_load_const_reg(list,OS_ADDR,-tarmprocinfo(current_procinfo).floatregstart,NR_R12);
 
1353
                    list.concat(taicpu.op_reg_reg_reg(A_SUB,NR_R12,current_procinfo.framepointer,NR_R12));
 
1354
                    ref.base:=NR_R12;
 
1355
                  end
 
1356
                else
 
1357
                  begin
 
1358
                    ref.base:=current_procinfo.framepointer;
 
1359
                    ref.offset:=tarmprocinfo(current_procinfo).floatregstart;
 
1360
                  end;
 
1361
                list.concat(taicpu.op_reg_const_ref(A_LFM,newreg(R_FPUREGISTER,firstfloatreg,R_SUBWHOLE),
 
1362
                  lastfloatreg-firstfloatreg+1,ref));
 
1363
              end;
 
1364
 
 
1365
            if (current_procinfo.framepointer=NR_STACK_POINTER_REG) then
 
1366
              begin
 
1367
                LocalSize:=current_procinfo.calc_stackframe_size;
 
1368
                if LocalSize<>0 then
 
1369
                  if not(is_shifter_const(LocalSize,shift)) then
 
1370
                    begin
 
1371
                      a_reg_alloc(list,NR_R12);
 
1372
                      a_load_const_reg(list,OS_ADDR,LocalSize,NR_R12);
 
1373
                      list.concat(taicpu.op_reg_reg_reg(A_ADD,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,NR_R12));
 
1374
                      a_reg_dealloc(list,NR_R12);
 
1375
                    end
 
1376
                  else
 
1377
                    begin
 
1378
                      list.concat(taicpu.op_reg_reg_const(A_ADD,NR_STACK_POINTER_REG,NR_STACK_POINTER_REG,LocalSize));
 
1379
                    end;
 
1380
 
 
1381
                regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
 
1382
                if (pi_do_call in current_procinfo.flags) or (regs<>[]) then
 
1383
                  begin
 
1384
                    exclude(regs,RS_R14);
 
1385
                    include(regs,RS_R15);
 
1386
                  end;
 
1387
                if regs=[] then
 
1388
                  list.concat(taicpu.op_reg_reg(A_MOV,NR_R15,NR_R14))
 
1389
                else
 
1390
                  begin
 
1391
                    reference_reset(ref);
 
1392
                    ref.index:=NR_STACK_POINTER_REG;
 
1393
                    ref.addressmode:=AM_PREINDEXED;
 
1394
                    list.concat(setoppostfix(taicpu.op_ref_regset(A_LDM,ref,regs),PF_FD));
 
1395
                  end;
 
1396
              end
 
1397
            else
 
1398
              begin
 
1399
                { restore int registers and return }
 
1400
                reference_reset(ref);
 
1401
                ref.index:=NR_FRAME_POINTER_REG;
 
1402
                list.concat(setoppostfix(taicpu.op_ref_regset(A_LDM,ref,rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall)+[RS_R11,RS_R13,RS_R15]),PF_EA));
 
1403
              end;
 
1404
          end
 
1405
        else
 
1406
          list.concat(taicpu.op_reg_reg(A_MOV,NR_PC,NR_R14));
 
1407
      end;
 
1408
 
 
1409
 
 
1410
    procedure tcgarm.a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);
 
1411
      var
 
1412
        b : byte;
 
1413
        tmpref : treference;
 
1414
        instr : taicpu;
 
1415
      begin
 
1416
        if ref.addressmode<>AM_OFFSET then
 
1417
          internalerror(200309071);
 
1418
        tmpref:=ref;
 
1419
        { Be sure to have a base register }
 
1420
        if (tmpref.base=NR_NO) then
 
1421
          begin
 
1422
            if tmpref.shiftmode<>SM_None then
 
1423
              internalerror(200308294);
 
1424
            if tmpref.signindex<0 then
 
1425
              internalerror(200312023);
 
1426
            tmpref.base:=tmpref.index;
 
1427
            tmpref.index:=NR_NO;
 
1428
          end;
 
1429
 
 
1430
        if assigned(tmpref.symbol) or
 
1431
           not((is_shifter_const(tmpref.offset,b)) or
 
1432
               (is_shifter_const(-tmpref.offset,b))
 
1433
              ) then
 
1434
          fixref(list,tmpref);
 
1435
 
 
1436
        { expect a base here if there is an index }
 
1437
        if (tmpref.base=NR_NO) and (tmpref.index<>NR_NO) then
 
1438
          internalerror(200312022);
 
1439
 
 
1440
        if tmpref.index<>NR_NO then
 
1441
          begin
 
1442
            if tmpref.shiftmode<>SM_None then
 
1443
              internalerror(200312021);
 
1444
            if tmpref.signindex<0 then
 
1445
              a_op_reg_reg_reg(list,OP_SUB,OS_ADDR,tmpref.base,tmpref.index,r)
 
1446
            else
 
1447
              a_op_reg_reg_reg(list,OP_ADD,OS_ADDR,tmpref.base,tmpref.index,r);
 
1448
            if tmpref.offset<>0 then
 
1449
              a_op_const_reg_reg(list,OP_ADD,OS_ADDR,tmpref.offset,r,r);
 
1450
          end
 
1451
        else
 
1452
          begin
 
1453
            if tmpref.base=NR_NO then
 
1454
              a_load_const_reg(list,OS_ADDR,tmpref.offset,r)
 
1455
            else
 
1456
              if tmpref.offset<>0 then
 
1457
                a_op_const_reg_reg(list,OP_ADD,OS_ADDR,tmpref.offset,tmpref.base,r)
 
1458
              else
 
1459
                begin
 
1460
                  instr:=taicpu.op_reg_reg(A_MOV,r,tmpref.base);
 
1461
                  list.concat(instr);
 
1462
                  add_move_instruction(instr);
 
1463
                end;
 
1464
          end;
 
1465
      end;
 
1466
 
 
1467
 
 
1468
    procedure tcgarm.fixref(list : TAsmList;var ref : treference);
 
1469
      var
 
1470
        tmpreg : tregister;
 
1471
        tmpref : treference;
 
1472
        l : tasmlabel;
 
1473
      begin
 
1474
        { absolute symbols can't be handled directly, we've to store the symbol reference
 
1475
          in the text segment and access it pc relative
 
1476
 
 
1477
          For now, we assume that references where base or index equals to PC are already
 
1478
          relative, all other references are assumed to be absolute and thus they need
 
1479
          to be handled extra.
 
1480
 
 
1481
          A proper solution would be to change refoptions to a set and store the information
 
1482
          if the symbol is absolute or relative there.
 
1483
        }
 
1484
        { create consts entry }
 
1485
        reference_reset(tmpref);
 
1486
        current_asmdata.getjumplabel(l);
 
1487
        cg.a_label(current_procinfo.aktlocaldata,l);
 
1488
        tmpref.symboldata:=current_procinfo.aktlocaldata.last;
 
1489
 
 
1490
        if assigned(ref.symbol) then
 
1491
          current_procinfo.aktlocaldata.concat(tai_const.create_sym_offset(ref.symbol,ref.offset))
 
1492
        else
 
1493
          current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(ref.offset));
 
1494
 
 
1495
        { load consts entry }
 
1496
        tmpreg:=getintregister(list,OS_INT);
 
1497
        tmpref.symbol:=l;
 
1498
        tmpref.base:=NR_PC;
 
1499
        list.concat(taicpu.op_reg_ref(A_LDR,tmpreg,tmpref));
 
1500
 
 
1501
        if (ref.base<>NR_NO) then
 
1502
          begin
 
1503
            if ref.index<>NR_NO then
 
1504
              begin
 
1505
                list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg));
 
1506
                ref.base:=tmpreg;
 
1507
              end
 
1508
            else
 
1509
              if ref.base<>NR_PC then
 
1510
                begin
 
1511
                  ref.index:=tmpreg;
 
1512
                  ref.shiftimm:=0;
 
1513
                  ref.signindex:=1;
 
1514
                  ref.shiftmode:=SM_None;
 
1515
                end
 
1516
                else
 
1517
                  ref.base:=tmpreg;
 
1518
          end
 
1519
        else
 
1520
          ref.base:=tmpreg;
 
1521
        ref.offset:=0;
 
1522
        ref.symbol:=nil;
 
1523
      end;
 
1524
 
 
1525
 
 
1526
    procedure tcgarm.g_concatcopy_move(list : TAsmList;const source,dest : treference;len : aint);
 
1527
      var
 
1528
        paraloc1,paraloc2,paraloc3 : TCGPara;
 
1529
      begin
 
1530
        paraloc1.init;
 
1531
        paraloc2.init;
 
1532
        paraloc3.init;
 
1533
        paramanager.getintparaloc(pocall_default,1,paraloc1);
 
1534
        paramanager.getintparaloc(pocall_default,2,paraloc2);
 
1535
        paramanager.getintparaloc(pocall_default,3,paraloc3);
 
1536
        paramanager.allocparaloc(list,paraloc3);
 
1537
        a_param_const(list,OS_INT,len,paraloc3);
 
1538
        paramanager.allocparaloc(list,paraloc2);
 
1539
        a_paramaddr_ref(list,dest,paraloc2);
 
1540
        paramanager.allocparaloc(list,paraloc2);
 
1541
        a_paramaddr_ref(list,source,paraloc1);
 
1542
        paramanager.freeparaloc(list,paraloc3);
 
1543
        paramanager.freeparaloc(list,paraloc2);
 
1544
        paramanager.freeparaloc(list,paraloc1);
 
1545
        alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
 
1546
        alloccpuregisters(list,R_FPUREGISTER,paramanager.get_volatile_registers_fpu(pocall_default));
 
1547
        a_call_name(list,'FPC_MOVE');
 
1548
        dealloccpuregisters(list,R_FPUREGISTER,paramanager.get_volatile_registers_fpu(pocall_default));
 
1549
        dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
 
1550
        paraloc3.done;
 
1551
        paraloc2.done;
 
1552
        paraloc1.done;
 
1553
      end;
 
1554
 
 
1555
 
 
1556
    procedure tcgarm.g_concatcopy_internal(list : TAsmList;const source,dest : treference;len : aint;aligned : boolean);
 
1557
      const
 
1558
        maxtmpreg=10;{roozbeh: can be reduced to 8 or lower if might conflick with reserved ones,also +2 is used becouse of regs required for referencing}
 
1559
 
 
1560
      var
 
1561
        srcref,dstref,usedtmpref,usedtmpref2:treference;
 
1562
        srcreg,destreg,countreg,r,tmpreg:tregister;
 
1563
        helpsize:aint;
 
1564
        copysize:byte;
 
1565
        cgsize:Tcgsize;
 
1566
        tmpregisters:array[1..maxtmpreg] of tregister;
 
1567
        tmpregi,tmpregi2:byte;
 
1568
 
 
1569
      { will never be called with count<=4 }
 
1570
      procedure genloop(count : aword;size : byte);
 
1571
        const
 
1572
          size2opsize : array[1..4] of tcgsize = (OS_8,OS_16,OS_NO,OS_32);
 
1573
        var
 
1574
          l : tasmlabel;
 
1575
        begin
 
1576
          current_asmdata.getjumplabel(l);
 
1577
          if count<size then size:=1;
 
1578
          a_load_const_reg(list,OS_INT,count div size,countreg);
 
1579
          cg.a_label(list,l);
 
1580
          srcref.addressmode:=AM_POSTINDEXED;
 
1581
          dstref.addressmode:=AM_POSTINDEXED;
 
1582
          srcref.offset:=size;
 
1583
          dstref.offset:=size;
 
1584
          r:=getintregister(list,size2opsize[size]);
 
1585
          a_load_ref_reg(list,size2opsize[size],size2opsize[size],srcref,r);
 
1586
          list.concat(setoppostfix(taicpu.op_reg_reg_const(A_SUB,countreg,countreg,1),PF_S));
 
1587
          a_load_reg_ref(list,size2opsize[size],size2opsize[size],r,dstref);
 
1588
          a_jmp_flags(list,F_NE,l);
 
1589
          srcref.offset:=1;
 
1590
          dstref.offset:=1;
 
1591
          case count mod size of
 
1592
            1:
 
1593
              begin
 
1594
                a_load_ref_reg(list,OS_8,OS_8,srcref,r);
 
1595
                a_load_reg_ref(list,OS_8,OS_8,r,dstref);
 
1596
              end;
 
1597
            2:
 
1598
              if aligned then
 
1599
                begin
 
1600
                  a_load_ref_reg(list,OS_16,OS_16,srcref,r);
 
1601
                  a_load_reg_ref(list,OS_16,OS_16,r,dstref);
 
1602
                end
 
1603
              else
 
1604
                begin
 
1605
                  a_load_ref_reg(list,OS_8,OS_8,srcref,r);
 
1606
                  a_load_reg_ref(list,OS_8,OS_8,r,dstref);
 
1607
                  a_load_ref_reg(list,OS_8,OS_8,srcref,r);
 
1608
                  a_load_reg_ref(list,OS_8,OS_8,r,dstref);
 
1609
                end;
 
1610
            3:
 
1611
              if aligned then
 
1612
                begin
 
1613
                  srcref.offset:=2;
 
1614
                  dstref.offset:=2;
 
1615
                  a_load_ref_reg(list,OS_16,OS_16,srcref,r);
 
1616
                  a_load_reg_ref(list,OS_16,OS_16,r,dstref);
 
1617
                  a_load_ref_reg(list,OS_8,OS_8,srcref,r);
 
1618
                  a_load_reg_ref(list,OS_8,OS_8,r,dstref);
 
1619
                end
 
1620
              else
 
1621
                begin
 
1622
                  a_load_ref_reg(list,OS_8,OS_8,srcref,r);
 
1623
                  a_load_reg_ref(list,OS_8,OS_8,r,dstref);
 
1624
                  a_load_ref_reg(list,OS_8,OS_8,srcref,r);
 
1625
                  a_load_reg_ref(list,OS_8,OS_8,r,dstref);
 
1626
                  a_load_ref_reg(list,OS_8,OS_8,srcref,r);
 
1627
                  a_load_reg_ref(list,OS_8,OS_8,r,dstref);
 
1628
                end;
 
1629
          end;
 
1630
          { keep the registers alive }
 
1631
          list.concat(taicpu.op_reg_reg(A_MOV,countreg,countreg));
 
1632
          list.concat(taicpu.op_reg_reg(A_MOV,srcreg,srcreg));
 
1633
          list.concat(taicpu.op_reg_reg(A_MOV,destreg,destreg));
 
1634
        end;
 
1635
 
 
1636
      begin
 
1637
        if len=0 then
 
1638
          exit;
 
1639
        helpsize:=12+maxtmpreg*4;//52 with maxtmpreg=10
 
1640
        dstref:=dest;
 
1641
        srcref:=source;
 
1642
        if cs_opt_size in current_settings.optimizerswitches then
 
1643
          helpsize:=8;
 
1644
        if (len<=helpsize) and aligned then
 
1645
          begin
 
1646
            tmpregi:=0;
 
1647
            srcreg:=getintregister(list,OS_ADDR);
 
1648
 
 
1649
            { explicit pc relative addressing, could be
 
1650
              e.g. a floating point constant }
 
1651
            if source.base=NR_PC then
 
1652
              begin
 
1653
                { ... then we don't need a loadaddr }
 
1654
                srcref:=source;
 
1655
              end
 
1656
            else
 
1657
              begin
 
1658
                a_loadaddr_ref_reg(list,source,srcreg);
 
1659
                reference_reset_base(srcref,srcreg,0);
 
1660
              end;
 
1661
 
 
1662
            while (len div 4 <> 0) and (tmpregi<maxtmpreg) do
 
1663
              begin
 
1664
                inc(tmpregi);
 
1665
                tmpregisters[tmpregi]:=getintregister(list,OS_32);
 
1666
                a_load_ref_reg(list,OS_32,OS_32,srcref,tmpregisters[tmpregi]);
 
1667
                inc(srcref.offset,4);
 
1668
                dec(len,4);
 
1669
              end;
 
1670
 
 
1671
            destreg:=getintregister(list,OS_ADDR);
 
1672
            a_loadaddr_ref_reg(list,dest,destreg);
 
1673
            reference_reset_base(dstref,destreg,0);
 
1674
            tmpregi2:=1;
 
1675
            while (tmpregi2<=tmpregi) do
 
1676
              begin
 
1677
                a_load_reg_ref(list,OS_32,OS_32,tmpregisters[tmpregi2],dstref);
 
1678
                inc(dstref.offset,4);
 
1679
                inc(tmpregi2);
 
1680
              end;
 
1681
 
 
1682
            copysize:=4;
 
1683
            cgsize:=OS_32;
 
1684
            while len<>0 do
 
1685
              begin
 
1686
                if len<2 then
 
1687
                  begin
 
1688
                    copysize:=1;
 
1689
                    cgsize:=OS_8;
 
1690
                  end
 
1691
                else if len<4 then
 
1692
                  begin
 
1693
                    copysize:=2;
 
1694
                    cgsize:=OS_16;
 
1695
                  end;
 
1696
                dec(len,copysize);
 
1697
                r:=getintregister(list,cgsize);
 
1698
                a_load_ref_reg(list,cgsize,cgsize,srcref,r);
 
1699
                a_load_reg_ref(list,cgsize,cgsize,r,dstref);
 
1700
                inc(srcref.offset,copysize);
 
1701
                inc(dstref.offset,copysize);
 
1702
              end;{end of while}
 
1703
          end
 
1704
        else
 
1705
          begin
 
1706
            cgsize:=OS_32;
 
1707
            if (len<=4) then{len<=4 and not aligned}
 
1708
              begin
 
1709
                r:=getintregister(list,cgsize);
 
1710
                usedtmpref:=a_internal_load_ref_reg(list,OS_8,OS_8,srcref,r);
 
1711
                if Len=1 then
 
1712
                  a_load_reg_ref(list,OS_8,OS_8,r,dstref)
 
1713
                else
 
1714
                  begin
 
1715
                    tmpreg:=getintregister(list,cgsize);
 
1716
                    usedtmpref2:=a_internal_load_reg_ref(list,OS_8,OS_8,r,dstref);
 
1717
                    inc(usedtmpref.offset,1);
 
1718
                    a_load_ref_reg(list,OS_8,OS_8,usedtmpref,tmpreg);
 
1719
                    inc(usedtmpref2.offset,1);
 
1720
                    a_load_reg_ref(list,OS_8,OS_8,tmpreg,usedtmpref2);
 
1721
                    if len>2 then
 
1722
                      begin
 
1723
                        inc(usedtmpref.offset,1);
 
1724
                        a_load_ref_reg(list,OS_8,OS_8,usedtmpref,tmpreg);
 
1725
                        inc(usedtmpref2.offset,1);
 
1726
                        a_load_reg_ref(list,OS_8,OS_8,tmpreg,usedtmpref2);
 
1727
                        if len>3 then
 
1728
                          begin
 
1729
                            inc(usedtmpref.offset,1);
 
1730
                            a_load_ref_reg(list,OS_8,OS_8,usedtmpref,tmpreg);
 
1731
                            inc(usedtmpref2.offset,1);
 
1732
                            a_load_reg_ref(list,OS_8,OS_8,tmpreg,usedtmpref2);
 
1733
                          end;
 
1734
                        end;
 
1735
                      end;
 
1736
            end{end of if len<=4}
 
1737
            else
 
1738
              begin{unaligned & 4<len<helpsize **or** aligned/unaligned & len>helpsize}
 
1739
                destreg:=getintregister(list,OS_ADDR);
 
1740
                a_loadaddr_ref_reg(list,dest,destreg);
 
1741
                reference_reset_base(dstref,destreg,0);
 
1742
 
 
1743
                srcreg:=getintregister(list,OS_ADDR);
 
1744
                a_loadaddr_ref_reg(list,source,srcreg);
 
1745
                reference_reset_base(srcref,srcreg,0);
 
1746
 
 
1747
                countreg:=getintregister(list,OS_32);
 
1748
 
 
1749
//            if cs_opt_size in current_settings.optimizerswitches  then
 
1750
                { roozbeh : it seems loading 1 byte is faster becouse of caching/fetching(?) }
 
1751
                {if aligned then
 
1752
                genloop(len,4)
 
1753
                else}
 
1754
                genloop(len,1);
 
1755
            end;
 
1756
          end;
 
1757
    end;
 
1758
 
 
1759
    procedure tcgarm.g_concatcopy_unaligned(list : TAsmList;const source,dest : treference;len : aint);
 
1760
      begin
 
1761
        g_concatcopy_internal(list,source,dest,len,false);
 
1762
      end;
 
1763
 
 
1764
 
 
1765
    procedure tcgarm.g_concatcopy(list : TAsmList;const source,dest : treference;len : aint);
 
1766
      begin
 
1767
        if (source.alignment in [1..3]) or
 
1768
          (dest.alignment in [1..3]) then
 
1769
          g_concatcopy_internal(list,source,dest,len,false)
 
1770
        else
 
1771
          g_concatcopy_internal(list,source,dest,len,true);
 
1772
      end;
 
1773
 
 
1774
 
 
1775
    procedure tcgarm.g_overflowCheck(list : TAsmList;const l : tlocation;def : tdef);
 
1776
      var
 
1777
        ovloc : tlocation;
 
1778
      begin
 
1779
        ovloc.loc:=LOC_VOID;
 
1780
        g_overflowCheck_loc(list,l,def,ovloc);
 
1781
      end;
 
1782
 
 
1783
 
 
1784
    procedure tcgarm.g_overflowCheck_loc(List:TAsmList;const Loc:TLocation;def:TDef;ovloc : tlocation);
 
1785
      var
 
1786
        hl : tasmlabel;
 
1787
        ai:TAiCpu;
 
1788
        hflags : tresflags;
 
1789
      begin
 
1790
        if not(cs_check_overflow in current_settings.localswitches) then
 
1791
          exit;
 
1792
        current_asmdata.getjumplabel(hl);
 
1793
        case ovloc.loc of
 
1794
          LOC_VOID:
 
1795
            begin
 
1796
              ai:=taicpu.op_sym(A_B,hl);
 
1797
              ai.is_jmp:=true;
 
1798
 
 
1799
              if not((def.typ=pointerdef) or
 
1800
                    ((def.typ=orddef) and
 
1801
                     (torddef(def).ordtype in [u64bit,u16bit,u32bit,u8bit,uchar,bool8bit,bool16bit,bool32bit]))) then
 
1802
                 ai.SetCondition(C_VC)
 
1803
              else
 
1804
                if TAiCpu(List.Last).opcode in [A_RSB,A_RSC,A_SBC,A_SUB] then
 
1805
                  ai.SetCondition(C_CS)
 
1806
                else
 
1807
                  ai.SetCondition(C_CC);
 
1808
 
 
1809
              list.concat(ai);
 
1810
            end;
 
1811
          LOC_FLAGS:
 
1812
            begin
 
1813
              hflags:=ovloc.resflags;
 
1814
              inverse_flags(hflags);
 
1815
              cg.a_jmp_flags(list,hflags,hl);
 
1816
            end;
 
1817
          else
 
1818
            internalerror(200409281);
 
1819
        end;
 
1820
 
 
1821
        a_call_name(list,'FPC_OVERFLOW');
 
1822
        a_label(list,hl);
 
1823
      end;
 
1824
 
 
1825
 
 
1826
    procedure tcgarm.g_save_standard_registers(list : TAsmList);
 
1827
      begin
 
1828
        { this work is done in g_proc_entry }
 
1829
      end;
 
1830
 
 
1831
 
 
1832
    procedure tcgarm.g_restore_standard_registers(list : TAsmList);
 
1833
      begin
 
1834
        { this work is done in g_proc_exit }
 
1835
      end;
 
1836
 
 
1837
 
 
1838
    procedure tcgarm.a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
 
1839
      var
 
1840
        ai : taicpu;
 
1841
      begin
 
1842
        ai:=Taicpu.Op_sym(A_B,l);
 
1843
        ai.SetCondition(OpCmp2AsmCond[cond]);
 
1844
        ai.is_jmp:=true;
 
1845
        list.concat(ai);
 
1846
      end;
 
1847
 
 
1848
 
 
1849
    procedure tcgarm.g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);
 
1850
 
 
1851
      procedure loadvmttor12;
 
1852
        var
 
1853
          href : treference;
 
1854
        begin
 
1855
          reference_reset_base(href,NR_R0,0);
 
1856
          cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_R12);
 
1857
        end;
 
1858
 
 
1859
 
 
1860
      procedure op_onr12methodaddr;
 
1861
        var
 
1862
          href : treference;
 
1863
        begin
 
1864
          if (procdef.extnumber=$ffff) then
 
1865
            Internalerror(200006139);
 
1866
          { call/jmp  vmtoffs(%eax) ; method offs }
 
1867
          reference_reset_base(href,NR_R12,procdef._class.vmtmethodoffset(procdef.extnumber));
 
1868
          cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_R12);
 
1869
          list.concat(taicpu.op_reg_reg(A_MOV,NR_PC,NR_R12));
 
1870
        end;
 
1871
 
 
1872
      var
 
1873
        make_global : boolean;
 
1874
      begin
 
1875
        if not(procdef.proctypeoption in [potype_function,potype_procedure]) then
 
1876
          Internalerror(200006137);
 
1877
        if not assigned(procdef._class) or
 
1878
           (procdef.procoptions*[po_classmethod, po_staticmethod,
 
1879
             po_methodpointer, po_interrupt, po_iocheck]<>[]) then
 
1880
          Internalerror(200006138);
 
1881
        if procdef.owner.symtabletype<>ObjectSymtable then
 
1882
          Internalerror(200109191);
 
1883
 
 
1884
        make_global:=false;
 
1885
        if (not current_module.is_unit) or
 
1886
           (cs_create_smart in current_settings.moduleswitches) or
 
1887
           (procdef.owner.defowner.owner.symtabletype=globalsymtable) then
 
1888
          make_global:=true;
 
1889
 
 
1890
        if make_global then
 
1891
          list.concat(Tai_symbol.Createname_global(labelname,AT_FUNCTION,0))
 
1892
        else
 
1893
          list.concat(Tai_symbol.Createname(labelname,AT_FUNCTION,0));
 
1894
 
 
1895
        { set param1 interface to self  }
 
1896
        g_adjust_self_value(list,procdef,ioffset);
 
1897
 
 
1898
        { case 4 }
 
1899
        if po_virtualmethod in procdef.procoptions then
 
1900
          begin
 
1901
            loadvmttor12;
 
1902
            op_onr12methodaddr;
 
1903
          end
 
1904
        { case 0 }
 
1905
        else
 
1906
          list.concat(taicpu.op_sym(A_B,current_asmdata.RefAsmSymbol(procdef.mangledname)));
 
1907
 
 
1908
        list.concat(Tai_symbol_end.Createname(labelname));
 
1909
      end;
 
1910
 
 
1911
 
 
1912
    procedure tcg64farm.a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);
 
1913
      begin
 
1914
        case op of
 
1915
          OP_NEG:
 
1916
            begin
 
1917
              list.concat(setoppostfix(taicpu.op_reg_reg_const(A_RSB,regdst.reglo,regsrc.reglo,0),PF_S));
 
1918
              list.concat(taicpu.op_reg_reg_const(A_RSC,regdst.reghi,regsrc.reghi,0));
 
1919
            end;
 
1920
          OP_NOT:
 
1921
            begin
 
1922
              cg.a_op_reg_reg(list,OP_NOT,OS_INT,regsrc.reglo,regdst.reglo);
 
1923
              cg.a_op_reg_reg(list,OP_NOT,OS_INT,regsrc.reghi,regdst.reghi);
 
1924
            end;
 
1925
          else
 
1926
            a_op64_reg_reg_reg(list,op,size,regsrc,regdst,regdst);
 
1927
        end;
 
1928
      end;
 
1929
 
 
1930
 
 
1931
    procedure tcg64farm.a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);
 
1932
      begin
 
1933
        a_op64_const_reg_reg(list,op,size,value,reg,reg);
 
1934
      end;
 
1935
 
 
1936
 
 
1937
    procedure tcg64farm.a_op64_const_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64);
 
1938
      var
 
1939
        ovloc : tlocation;
 
1940
      begin
 
1941
        a_op64_const_reg_reg_checkoverflow(list,op,size,value,regsrc,regdst,false,ovloc);
 
1942
      end;
 
1943
 
 
1944
 
 
1945
    procedure tcg64farm.a_op64_reg_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64);
 
1946
      var
 
1947
        ovloc : tlocation;
 
1948
      begin
 
1949
        a_op64_reg_reg_reg_checkoverflow(list,op,size,regsrc1,regsrc2,regdst,false,ovloc);
 
1950
      end;
 
1951
 
 
1952
 
 
1953
    procedure tcg64farm.a_op64_const_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64;setflags : boolean;var ovloc : tlocation);
 
1954
      var
 
1955
        tmpreg : tregister;
 
1956
        b : byte;
 
1957
      begin
 
1958
        ovloc.loc:=LOC_VOID;
 
1959
        case op of
 
1960
          OP_NEG,
 
1961
          OP_NOT :
 
1962
            internalerror(200306017);
 
1963
        end;
 
1964
        if (setflags or tcgarm(cg).cgsetflags) and (op in [OP_ADD,OP_SUB]) then
 
1965
          begin
 
1966
            case op of
 
1967
              OP_ADD:
 
1968
                begin
 
1969
                  if is_shifter_const(lo(value),b) then
 
1970
                    list.concat(setoppostfix(taicpu.op_reg_reg_const(A_ADD,regdst.reglo,regsrc.reglo,lo(value)),PF_S))
 
1971
                  else
 
1972
                    begin
 
1973
                      tmpreg:=cg.getintregister(list,OS_32);
 
1974
                      cg.a_load_const_reg(list,OS_32,lo(value),tmpreg);
 
1975
                      list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ADD,regdst.reglo,regsrc.reglo,tmpreg),PF_S));
 
1976
                    end;
 
1977
 
 
1978
                  if is_shifter_const(hi(value),b) then
 
1979
                    list.concat(setoppostfix(taicpu.op_reg_reg_const(A_ADC,regdst.reghi,regsrc.reghi,hi(value)),PF_S))
 
1980
                  else
 
1981
                    begin
 
1982
                      tmpreg:=cg.getintregister(list,OS_32);
 
1983
                      cg.a_load_const_reg(list,OS_32,hi(value),tmpreg);
 
1984
                      list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ADC,regdst.reghi,regsrc.reghi,tmpreg),PF_S));
 
1985
                    end;
 
1986
                end;
 
1987
              OP_SUB:
 
1988
                begin
 
1989
                  if is_shifter_const(lo(value),b) then
 
1990
                    list.concat(setoppostfix(taicpu.op_reg_reg_const(A_SUB,regdst.reglo,regsrc.reglo,lo(value)),PF_S))
 
1991
                  else
 
1992
                    begin
 
1993
                      tmpreg:=cg.getintregister(list,OS_32);
 
1994
                      cg.a_load_const_reg(list,OS_32,lo(value),tmpreg);
 
1995
                      list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_SUB,regdst.reglo,regsrc.reglo,tmpreg),PF_S));
 
1996
                    end;
 
1997
 
 
1998
                  if is_shifter_const(hi(value),b) then
 
1999
                    list.concat(setoppostfix(taicpu.op_reg_reg_const(A_SBC,regdst.reghi,regsrc.reghi,aint(hi(value))),PF_S))
 
2000
                  else
 
2001
                    begin
 
2002
                      tmpreg:=cg.getintregister(list,OS_32);
 
2003
                      cg.a_load_const_reg(list,OS_32,hi(value),tmpreg);
 
2004
                      list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_SBC,regdst.reghi,regsrc.reghi,tmpreg),PF_S));
 
2005
                    end;
 
2006
                end;
 
2007
              else
 
2008
                internalerror(200502131);
 
2009
            end;
 
2010
            if size=OS_64 then
 
2011
              begin
 
2012
                { the arm has an weired opinion how flags for SUB/ADD are handled }
 
2013
                ovloc.loc:=LOC_FLAGS;
 
2014
                case op of
 
2015
                  OP_ADD:
 
2016
                    ovloc.resflags:=F_CS;
 
2017
                  OP_SUB:
 
2018
                    ovloc.resflags:=F_CC;
 
2019
                end;
 
2020
              end;
 
2021
          end
 
2022
        else
 
2023
          begin
 
2024
            case op of
 
2025
              OP_AND,OP_OR,OP_XOR:
 
2026
                begin
 
2027
                  cg.a_op_const_reg_reg(list,op,OS_32,aint(lo(value)),regsrc.reglo,regdst.reglo);
 
2028
                  cg.a_op_const_reg_reg(list,op,OS_32,aint(hi(value)),regsrc.reghi,regdst.reghi);
 
2029
                end;
 
2030
              OP_ADD:
 
2031
                begin
 
2032
                  if is_shifter_const(aint(lo(value)),b) then
 
2033
                    list.concat(setoppostfix(taicpu.op_reg_reg_const(A_ADD,regdst.reglo,regsrc.reglo,aint(lo(value))),PF_S))
 
2034
                  else
 
2035
                    begin
 
2036
                      tmpreg:=cg.getintregister(list,OS_32);
 
2037
                      cg.a_load_const_reg(list,OS_32,aint(lo(value)),tmpreg);
 
2038
                      list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ADD,regdst.reglo,regsrc.reglo,tmpreg),PF_S));
 
2039
                    end;
 
2040
 
 
2041
                  if is_shifter_const(aint(hi(value)),b) then
 
2042
                    list.concat(taicpu.op_reg_reg_const(A_ADC,regdst.reghi,regsrc.reghi,aint(hi(value))))
 
2043
                  else
 
2044
                    begin
 
2045
                      tmpreg:=cg.getintregister(list,OS_32);
 
2046
                      cg.a_load_const_reg(list,OS_32,aint(hi(value)),tmpreg);
 
2047
                      list.concat(taicpu.op_reg_reg_reg(A_ADC,regdst.reghi,regsrc.reghi,tmpreg));
 
2048
                    end;
 
2049
                end;
 
2050
              OP_SUB:
 
2051
                begin
 
2052
                  if is_shifter_const(aint(lo(value)),b) then
 
2053
                    list.concat(setoppostfix(taicpu.op_reg_reg_const(A_SUB,regdst.reglo,regsrc.reglo,aint(lo(value))),PF_S))
 
2054
                  else
 
2055
                    begin
 
2056
                      tmpreg:=cg.getintregister(list,OS_32);
 
2057
                      cg.a_load_const_reg(list,OS_32,aint(lo(value)),tmpreg);
 
2058
                      list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_SUB,regdst.reglo,regsrc.reglo,tmpreg),PF_S));
 
2059
                    end;
 
2060
 
 
2061
                  if is_shifter_const(aint(hi(value)),b) then
 
2062
                    list.concat(taicpu.op_reg_reg_const(A_SBC,regdst.reghi,regsrc.reghi,aint(hi(value))))
 
2063
                  else
 
2064
                    begin
 
2065
                      tmpreg:=cg.getintregister(list,OS_32);
 
2066
                      cg.a_load_const_reg(list,OS_32,hi(value),tmpreg);
 
2067
                      list.concat(taicpu.op_reg_reg_reg(A_SBC,regdst.reghi,regsrc.reghi,tmpreg));
 
2068
                    end;
 
2069
                end;
 
2070
            else
 
2071
              internalerror(2003083101);
 
2072
          end;
 
2073
        end;
 
2074
      end;
 
2075
 
 
2076
 
 
2077
    procedure tcg64farm.a_op64_reg_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64;setflags : boolean;var ovloc : tlocation);
 
2078
      begin
 
2079
        ovloc.loc:=LOC_VOID;
 
2080
        case op of
 
2081
          OP_NEG,
 
2082
          OP_NOT :
 
2083
            internalerror(200306017);
 
2084
        end;
 
2085
        if (setflags or tcgarm(cg).cgsetflags) and (op in [OP_ADD,OP_SUB]) then
 
2086
          begin
 
2087
            case op of
 
2088
              OP_ADD:
 
2089
                begin
 
2090
                  list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ADD,regdst.reglo,regsrc1.reglo,regsrc2.reglo),PF_S));
 
2091
                  list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ADC,regdst.reghi,regsrc1.reghi,regsrc2.reghi),PF_S));
 
2092
                end;
 
2093
              OP_SUB:
 
2094
                begin
 
2095
                  list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_SUB,regdst.reglo,regsrc2.reglo,regsrc1.reglo),PF_S));
 
2096
                  list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_SBC,regdst.reghi,regsrc2.reghi,regsrc1.reghi),PF_S));
 
2097
                end;
 
2098
              else
 
2099
                internalerror(2003083101);
 
2100
            end;
 
2101
            if size=OS_64 then
 
2102
              begin
 
2103
                { the arm has an weired opinion how flags for SUB/ADD are handled }
 
2104
                ovloc.loc:=LOC_FLAGS;
 
2105
                case op of
 
2106
                  OP_ADD:
 
2107
                    ovloc.resflags:=F_CS;
 
2108
                  OP_SUB:
 
2109
                    ovloc.resflags:=F_CC;
 
2110
                end;
 
2111
              end;
 
2112
          end
 
2113
        else
 
2114
          begin
 
2115
            case op of
 
2116
              OP_AND,OP_OR,OP_XOR:
 
2117
                begin
 
2118
                  cg.a_op_reg_reg_reg(list,op,OS_32,regsrc1.reglo,regsrc2.reglo,regdst.reglo);
 
2119
                  cg.a_op_reg_reg_reg(list,op,OS_32,regsrc1.reghi,regsrc2.reghi,regdst.reghi);
 
2120
                end;
 
2121
              OP_ADD:
 
2122
                begin
 
2123
                  list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ADD,regdst.reglo,regsrc1.reglo,regsrc2.reglo),PF_S));
 
2124
                  list.concat(taicpu.op_reg_reg_reg(A_ADC,regdst.reghi,regsrc1.reghi,regsrc2.reghi));
 
2125
                end;
 
2126
              OP_SUB:
 
2127
                begin
 
2128
                  list.concat(setoppostfix(taicpu.op_reg_reg_reg(A_SUB,regdst.reglo,regsrc2.reglo,regsrc1.reglo),PF_S));
 
2129
                  list.concat(taicpu.op_reg_reg_reg(A_SBC,regdst.reghi,regsrc2.reghi,regsrc1.reghi));
 
2130
                end;
 
2131
              else
 
2132
                internalerror(2003083101);
 
2133
            end;
 
2134
          end;
 
2135
      end;
 
2136
 
 
2137
 
 
2138
begin
 
2139
  cg:=tcgarm.create;
 
2140
  cg64:=tcg64farm.create;
 
2141
end.