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

« back to all changes in this revision

Viewing changes to fpcsrc/compiler/powerpc/rappcgas.pas

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

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

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
{
 
2
    Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
 
3
 
 
4
    Does the parsing for the PowerPC GNU AS styled inline assembler.
 
5
 
 
6
    This program is free software; you can redistribute it and/or modify
 
7
    it under the terms of the GNU General Public License as published by
 
8
    the Free Software Foundation; either version 2 of the License, or
 
9
    (at your option) any later version.
 
10
 
 
11
    This program is distributed in the hope that it will be useful,
 
12
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
    GNU General Public License for more details.
 
15
 
 
16
    You should have received a copy of the GNU General Public License
 
17
    along with this program; if not, write to the Free Software
 
18
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
19
 
 
20
 ****************************************************************************
 
21
}
 
22
Unit rappcgas;
 
23
 
 
24
{$i fpcdefs.inc}
 
25
 
 
26
  Interface
 
27
 
 
28
    uses
 
29
      raatt,rappc;
 
30
 
 
31
    type
 
32
      tppcattreader = class(tattreader)
 
33
        function is_asmopcode(const s: string):boolean;override;
 
34
        procedure handleopcode;override;
 
35
        procedure BuildReference(oper : tppcoperand);
 
36
        procedure BuildOperand(oper : tppcoperand);
 
37
        procedure BuildOpCode(instr : tppcinstruction);
 
38
        procedure ReadAt(oper : tppcoperand);
 
39
        procedure ReadSym(oper : tppcoperand);
 
40
        procedure ConvertCalljmp(instr : tppcinstruction);
 
41
      end;
 
42
 
 
43
 
 
44
  Implementation
 
45
 
 
46
    uses
 
47
      { helpers }
 
48
      cutils,
 
49
      { global }
 
50
      globtype,verbose,
 
51
      systems,
 
52
      { aasm }
 
53
      cpubase,aasmbase,aasmtai,aasmdata,aasmcpu,
 
54
      { symtable }
 
55
      symconst,symsym,
 
56
      { parser }
 
57
      procinfo,
 
58
      rabase,rautils,
 
59
      cgbase,cgobj
 
60
      ;
 
61
 
 
62
    procedure tppcattreader.ReadSym(oper : tppcoperand);
 
63
      var
 
64
         tempstr, mangledname : string;
 
65
         typesize,l,k : aint;
 
66
      begin
 
67
        tempstr:=actasmpattern;
 
68
        Consume(AS_ID);
 
69
        { typecasting? }
 
70
        if (actasmtoken=AS_LPAREN) and
 
71
           SearchType(tempstr,typesize) then
 
72
         begin
 
73
           oper.hastype:=true;
 
74
           Consume(AS_LPAREN);
 
75
           BuildOperand(oper);
 
76
           Consume(AS_RPAREN);
 
77
           if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
 
78
             oper.SetSize(typesize,true);
 
79
         end
 
80
        else
 
81
         if not oper.SetupVar(tempstr,false) then
 
82
          Message1(sym_e_unknown_id,tempstr);
 
83
        { record.field ? }
 
84
        if actasmtoken=AS_DOT then
 
85
         begin
 
86
           BuildRecordOffsetSize(tempstr,l,k,mangledname,false);
 
87
           if (mangledname<>'') then
 
88
             Message(asmr_e_invalid_reference_syntax);
 
89
           inc(oper.opr.ref.offset,l);
 
90
         end;
 
91
      end;
 
92
 
 
93
 
 
94
    procedure tppcattreader.ReadAt(oper : tppcoperand);
 
95
      begin
 
96
        { check for ...@ }
 
97
        if actasmtoken=AS_AT then
 
98
          begin
 
99
            if (oper.opr.ref.symbol=nil) and
 
100
               (oper.opr.ref.offset = 0) then
 
101
              Message(asmr_e_invalid_reference_syntax);
 
102
            Consume(AS_AT);
 
103
            if actasmtoken=AS_ID then
 
104
              begin
 
105
                if upper(actasmpattern)='L' then
 
106
                  oper.opr.ref.refaddr:=addr_lo
 
107
                else if upper(actasmpattern)='HA' then
 
108
                  oper.opr.ref.refaddr:=addr_hi
 
109
                else
 
110
                  Message(asmr_e_invalid_reference_syntax);
 
111
                Consume(AS_ID);
 
112
              end
 
113
            else
 
114
              Message(asmr_e_invalid_reference_syntax);
 
115
          end;
 
116
      end;
 
117
 
 
118
 
 
119
    Procedure tppcattreader.BuildReference(oper : tppcoperand);
 
120
 
 
121
      procedure Consume_RParen;
 
122
        begin
 
123
          if actasmtoken <> AS_RPAREN then
 
124
           Begin
 
125
             Message(asmr_e_invalid_reference_syntax);
 
126
             RecoverConsume(true);
 
127
           end
 
128
          else
 
129
           begin
 
130
             Consume(AS_RPAREN);
 
131
             if not (actasmtoken in [AS_COMMA,AS_SEPARATOR,AS_END]) then
 
132
              Begin
 
133
                Message(asmr_e_invalid_reference_syntax);
 
134
                RecoverConsume(true);
 
135
              end;
 
136
           end;
 
137
        end;
 
138
 
 
139
      var
 
140
        l : aint;
 
141
 
 
142
      begin
 
143
        Consume(AS_LPAREN);
 
144
        Case actasmtoken of
 
145
          AS_INTNUM,
 
146
          AS_MINUS,
 
147
          AS_PLUS:
 
148
            Begin
 
149
              { offset(offset) is invalid }
 
150
              If oper.opr.Ref.Offset <> 0 Then
 
151
               Begin
 
152
                 Message(asmr_e_invalid_reference_syntax);
 
153
                 RecoverConsume(true);
 
154
               End
 
155
              Else
 
156
               Begin
 
157
                 oper.opr.Ref.Offset:=BuildConstExpression(false,true);
 
158
                 Consume(AS_RPAREN);
 
159
                 if actasmtoken=AS_AT then
 
160
                   ReadAt(oper);
 
161
               end;
 
162
              exit;
 
163
            End;
 
164
          AS_REGISTER: { (reg ...  }
 
165
            Begin
 
166
              if ((oper.opr.typ=OPR_REFERENCE) and (oper.opr.ref.base<>NR_NO)) or
 
167
                 ((oper.opr.typ=OPR_LOCAL) and (oper.opr.localsym.localloc.loc<>LOC_REGISTER)) then
 
168
                message(asmr_e_cannot_index_relative_var);
 
169
              oper.opr.ref.base:=actasmregister;
 
170
              Consume(AS_REGISTER);
 
171
              { can either be a register or a right parenthesis }
 
172
              { (reg)        }
 
173
              if actasmtoken=AS_RPAREN then
 
174
               Begin
 
175
                 Consume_RParen;
 
176
                 exit;
 
177
               end;
 
178
              { (reg,reg ..  }
 
179
              Consume(AS_COMMA);
 
180
              if (actasmtoken=AS_REGISTER) and
 
181
                 (oper.opr.Ref.Offset = 0) then
 
182
               Begin
 
183
                 oper.opr.ref.index:=actasmregister;
 
184
                 Consume(AS_REGISTER);
 
185
                 Consume_RParen;
 
186
               end
 
187
              else
 
188
               Begin
 
189
                 Message(asmr_e_invalid_reference_syntax);
 
190
                 RecoverConsume(false);
 
191
               end;
 
192
            end; {end case }
 
193
          AS_ID:
 
194
            Begin
 
195
              ReadSym(oper);
 
196
              { add a constant expression? }
 
197
              if (actasmtoken=AS_PLUS) then
 
198
               begin
 
199
                 l:=BuildConstExpression(true,true);
 
200
                 case oper.opr.typ of
 
201
                   OPR_CONSTANT :
 
202
                     inc(oper.opr.val,l);
 
203
                   OPR_LOCAL :
 
204
                     inc(oper.opr.localsymofs,l);
 
205
                   OPR_REFERENCE :
 
206
                     inc(oper.opr.ref.offset,l);
 
207
                   else
 
208
                     internalerror(200309202);
 
209
                 end;
 
210
               end;
 
211
              Consume(AS_RPAREN);
 
212
              if actasmtoken=AS_AT then
 
213
                ReadAt(oper);
 
214
            End;
 
215
          AS_COMMA: { (, ...  can either be scaling, or index }
 
216
            Begin
 
217
              Consume(AS_COMMA);
 
218
              { Index }
 
219
              if (actasmtoken=AS_REGISTER) then
 
220
                Begin
 
221
                  oper.opr.ref.index:=actasmregister;
 
222
                  Consume(AS_REGISTER);
 
223
                  { check for scaling ... }
 
224
                  Consume_RParen;
 
225
                end
 
226
              else
 
227
                begin
 
228
                  Message(asmr_e_invalid_reference_syntax);
 
229
                  RecoverConsume(false);
 
230
                end;
 
231
            end;
 
232
        else
 
233
          Begin
 
234
            Message(asmr_e_invalid_reference_syntax);
 
235
            RecoverConsume(false);
 
236
          end;
 
237
        end;
 
238
      end;
 
239
 
 
240
 
 
241
    Procedure tppcattreader.BuildOperand(oper : tppcoperand);
 
242
      var
 
243
        expr : string;
 
244
        typesize,l : aint;
 
245
 
 
246
 
 
247
        procedure AddLabelOperand(hl:tasmlabel);
 
248
          begin
 
249
            if not(actasmtoken in [AS_PLUS,AS_MINUS,AS_LPAREN]) and
 
250
               is_calljmp(actopcode) then
 
251
             begin
 
252
               oper.opr.typ:=OPR_SYMBOL;
 
253
               oper.opr.symbol:=hl;
 
254
             end
 
255
            else
 
256
             begin
 
257
               oper.InitRef;
 
258
               oper.opr.ref.symbol:=hl;
 
259
             end;
 
260
          end;
 
261
 
 
262
 
 
263
        procedure MaybeRecordOffset;
 
264
          var
 
265
            mangledname: string;
 
266
            hasdot  : boolean;
 
267
            l,
 
268
            toffset,
 
269
            tsize   : aint;
 
270
          begin
 
271
            if not(actasmtoken in [AS_DOT,AS_PLUS,AS_MINUS]) then
 
272
             exit;
 
273
            l:=0;
 
274
            hasdot:=(actasmtoken=AS_DOT);
 
275
            if hasdot then
 
276
              begin
 
277
                if expr<>'' then
 
278
                  begin
 
279
                    BuildRecordOffsetSize(expr,toffset,tsize,mangledname,false);
 
280
                    if (oper.opr.typ<>OPR_CONSTANT) and
 
281
                       (mangledname<>'') then
 
282
                      Message(asmr_e_wrong_sym_type);
 
283
                    inc(l,toffset);
 
284
                    oper.SetSize(tsize,true);
 
285
                  end;
 
286
              end;
 
287
            if actasmtoken in [AS_PLUS,AS_MINUS] then
 
288
              inc(l,BuildConstExpression(true,false));
 
289
            case oper.opr.typ of
 
290
              OPR_LOCAL :
 
291
                begin
 
292
                  { don't allow direct access to fields of parameters, because that
 
293
                    will generate buggy code. Allow it only for explicit typecasting }
 
294
                  if hasdot and
 
295
                     (not oper.hastype) and
 
296
                     (tabstractvarsym(oper.opr.localsym).owner.symtabletype=parasymtable) and
 
297
                     (current_procinfo.procdef.proccalloption<>pocall_register) then
 
298
                    Message(asmr_e_cannot_access_field_directly_for_parameters);
 
299
                  inc(oper.opr.localsymofs,l)
 
300
                end;
 
301
              OPR_CONSTANT :
 
302
                if (mangledname<>'') then
 
303
                  begin
 
304
                    if (oper.opr.val<>0) then
 
305
                      Message(asmr_e_wrong_sym_type);
 
306
                    oper.opr.typ:=OPR_SYMBOL;
 
307
                    oper.opr.symbol:=current_asmdata.RefAsmSymbol(mangledname);
 
308
                  end
 
309
                else
 
310
                  inc(oper.opr.val,l);
 
311
              OPR_REFERENCE :
 
312
                inc(oper.opr.ref.offset,l);
 
313
              OPR_SYMBOL:
 
314
                Message(asmr_e_invalid_symbol_ref);
 
315
              else
 
316
                internalerror(200309221);
 
317
            end;
 
318
          end;
 
319
 
 
320
 
 
321
        function MaybeBuildReference:boolean;
 
322
          { Try to create a reference, if not a reference is found then false
 
323
            is returned }
 
324
          begin
 
325
            MaybeBuildReference:=true;
 
326
            case actasmtoken of
 
327
              AS_INTNUM,
 
328
              AS_MINUS,
 
329
              AS_PLUS:
 
330
                Begin
 
331
                  oper.opr.ref.offset:=BuildConstExpression(True,False);
 
332
                  if actasmtoken<>AS_LPAREN then
 
333
                    Message(asmr_e_invalid_reference_syntax)
 
334
                  else
 
335
                    BuildReference(oper);
 
336
                end;
 
337
              AS_LPAREN:
 
338
                BuildReference(oper);
 
339
              AS_ID: { only a variable is allowed ... }
 
340
                Begin
 
341
                  ReadSym(oper);
 
342
                  case actasmtoken of
 
343
                    AS_END,
 
344
                    AS_SEPARATOR,
 
345
                    AS_COMMA: ;
 
346
                    AS_LPAREN:
 
347
                      BuildReference(oper);
 
348
                  else
 
349
                    Begin
 
350
                      Message(asmr_e_invalid_reference_syntax);
 
351
                      Consume(actasmtoken);
 
352
                    end;
 
353
                  end; {end case }
 
354
                end;
 
355
              else
 
356
               MaybeBuildReference:=false;
 
357
            end; { end case }
 
358
          end;
 
359
 
 
360
 
 
361
      var
 
362
        tempreg : tregister;
 
363
        hl : tasmlabel;
 
364
        ofs : aint;
 
365
      Begin
 
366
        expr:='';
 
367
        case actasmtoken of
 
368
          AS_LPAREN: { Memory reference or constant expression }
 
369
            Begin
 
370
              oper.InitRef;
 
371
              BuildReference(oper);
 
372
            end;
 
373
 
 
374
          AS_INTNUM,
 
375
          AS_MINUS,
 
376
          AS_PLUS:
 
377
            Begin
 
378
              { Constant memory offset }
 
379
              { This must absolutely be followed by (  }
 
380
              oper.InitRef;
 
381
              oper.opr.ref.offset:=BuildConstExpression(True,False);
 
382
              if actasmtoken<>AS_LPAREN then
 
383
                begin
 
384
                  ofs:=oper.opr.ref.offset;
 
385
                  BuildConstantOperand(oper);
 
386
                  inc(oper.opr.val,ofs);
 
387
                end
 
388
              else
 
389
                BuildReference(oper);
 
390
            end;
 
391
 
 
392
          AS_ID: { A constant expression, or a Variable ref.  }
 
393
            Begin
 
394
              { Local Label ? }
 
395
              if is_locallabel(actasmpattern) then
 
396
               begin
 
397
                 CreateLocalLabel(actasmpattern,hl,false);
 
398
                 Consume(AS_ID);
 
399
                 AddLabelOperand(hl);
 
400
               end
 
401
              else
 
402
               { Check for label }
 
403
               if SearchLabel(actasmpattern,hl,false) then
 
404
                begin
 
405
                  Consume(AS_ID);
 
406
                  AddLabelOperand(hl);
 
407
                end
 
408
              else
 
409
               { probably a variable or normal expression }
 
410
               { or a procedure (such as in CALL ID)      }
 
411
               Begin
 
412
                 { is it a constant ? }
 
413
                 if SearchIConstant(actasmpattern,l) then
 
414
                  Begin
 
415
                    if not (oper.opr.typ in [OPR_NONE,OPR_CONSTANT]) then
 
416
                     Message(asmr_e_invalid_operand_type);
 
417
                    BuildConstantOperand(oper);
 
418
                  end
 
419
                 else
 
420
                  begin
 
421
                    expr:=actasmpattern;
 
422
                    Consume(AS_ID);
 
423
                    { typecasting? }
 
424
                    if (actasmtoken=AS_LPAREN) and
 
425
                       SearchType(expr,typesize) then
 
426
                     begin
 
427
                       oper.hastype:=true;
 
428
                       Consume(AS_LPAREN);
 
429
                       BuildOperand(oper);
 
430
                       Consume(AS_RPAREN);
 
431
                       if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
 
432
                         oper.SetSize(typesize,true);
 
433
                     end
 
434
                    else
 
435
                     begin
 
436
                       if oper.SetupVar(expr,false) then
 
437
                         ReadAt(oper)
 
438
                       else
 
439
                        Begin
 
440
                          { look for special symbols ... }
 
441
                          if expr= '__HIGH' then
 
442
                            begin
 
443
                              consume(AS_LPAREN);
 
444
                              if not oper.setupvar('high'+actasmpattern,false) then
 
445
                                Message1(sym_e_unknown_id,'high'+actasmpattern);
 
446
                              consume(AS_ID);
 
447
                              consume(AS_RPAREN);
 
448
                            end
 
449
                          else
 
450
                           if expr = '__RESULT' then
 
451
                            oper.SetUpResult
 
452
                          else
 
453
                           if expr = '__SELF' then
 
454
                            oper.SetupSelf
 
455
                          else
 
456
                           if expr = '__OLDEBP' then
 
457
                            oper.SetupOldEBP
 
458
                          else
 
459
                            Message1(sym_e_unknown_id,expr);
 
460
                        end;
 
461
                     end;
 
462
                  end;
 
463
                  if actasmtoken=AS_DOT then
 
464
                    MaybeRecordOffset;
 
465
                  { add a constant expression? }
 
466
                  if (actasmtoken=AS_PLUS) then
 
467
                   begin
 
468
                     l:=BuildConstExpression(true,false);
 
469
                     case oper.opr.typ of
 
470
                       OPR_CONSTANT :
 
471
                         inc(oper.opr.val,l);
 
472
                       OPR_LOCAL :
 
473
                         inc(oper.opr.localsymofs,l);
 
474
                       OPR_REFERENCE :
 
475
                         inc(oper.opr.ref.offset,l);
 
476
                       else
 
477
                         internalerror(200309202);
 
478
                     end;
 
479
                   end
 
480
               end;
 
481
              { Do we have a indexing reference, then parse it also }
 
482
              if actasmtoken=AS_LPAREN then
 
483
                BuildReference(oper);
 
484
            end;
 
485
 
 
486
          AS_REGISTER: { Register, a variable reference or a constant reference  }
 
487
            Begin
 
488
              { save the type of register used. }
 
489
              tempreg:=actasmregister;
 
490
              Consume(AS_REGISTER);
 
491
              if (actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) then
 
492
                if is_condreg(tempreg) and
 
493
                   ((actopcode = A_BC) or
 
494
                    (actopcode = A_BCCTR) or
 
495
                    (actopcode = A_BCLR) or
 
496
                    (actopcode = A_TW) or
 
497
                    (actopcode = A_TWI)) then
 
498
                  begin
 
499
                    { it isn't a real operand, everything is stored in the condition }
 
500
                    oper.opr.typ:=OPR_NONE;
 
501
                    actcondition.cr := getsupreg(tempreg);
 
502
                  end
 
503
                else
 
504
                  begin
 
505
                    if not (oper.opr.typ in [OPR_NONE,OPR_REGISTER]) then
 
506
                      Message(asmr_e_invalid_operand_type);
 
507
                    oper.opr.typ:=OPR_REGISTER;
 
508
                    oper.opr.reg:=tempreg;
 
509
                  end
 
510
              else if is_condreg(tempreg) then
 
511
                begin
 
512
                  if not(actcondition.cond in [C_T..C_DZF]) then
 
513
                    Message(asmr_e_syn_operand);
 
514
                  if actasmtoken=AS_STAR then
 
515
                    begin
 
516
                      consume(AS_STAR);
 
517
                      if (actasmtoken=AS_INTNUM) then
 
518
                        begin
 
519
                          consume(AS_INTNUM);
 
520
                          if actasmtoken=AS_PLUS then
 
521
                            begin
 
522
                              consume(AS_PLUS);
 
523
                              if (actasmtoken=AS_ID) then
 
524
                                begin
 
525
                                  oper.opr.typ:=OPR_NONE;
 
526
                                  if actasmpattern='LT' then
 
527
                                    actcondition.crbit:=(getsupreg(tempreg)-(RS_CR0))*4
 
528
                                  else if actasmpattern='GT' then
 
529
                                    actcondition.crbit:=(getsupreg(tempreg)-(RS_CR0))*4+1
 
530
                                  else if actasmpattern='EQ' then
 
531
                                    actcondition.crbit:=(getsupreg(tempreg)-(RS_CR0))*4+2
 
532
                                  else if actasmpattern='SO' then
 
533
                                    actcondition.crbit:=(getsupreg(tempreg)-(RS_CR0))*4+3
 
534
                                  else
 
535
                                    Message(asmr_e_syn_operand);
 
536
                                  consume(AS_ID);
 
537
                                end
 
538
                              else
 
539
                                Message(asmr_e_syn_operand);
 
540
                            end
 
541
                          else
 
542
                            Message(asmr_e_syn_operand);
 
543
                        end
 
544
                      else
 
545
                        Message(asmr_e_syn_operand);
 
546
                    end
 
547
                  else
 
548
                    Message(asmr_e_syn_operand);
 
549
                end
 
550
              else
 
551
                Message(asmr_e_syn_operand);
 
552
            end;
 
553
          AS_END,
 
554
          AS_SEPARATOR,
 
555
          AS_COMMA: ;
 
556
        else
 
557
          Begin
 
558
            Message(asmr_e_syn_operand);
 
559
            Consume(actasmtoken);
 
560
          end;
 
561
        end; { end case }
 
562
      end;
 
563
 
 
564
 
 
565
{*****************************************************************************
 
566
                                tppcattreader
 
567
*****************************************************************************}
 
568
 
 
569
    procedure tppcattreader.BuildOpCode(instr : tppcinstruction);
 
570
      var
 
571
        operandnum : longint;
 
572
      Begin
 
573
        { opcode }
 
574
        if (actasmtoken<>AS_OPCODE) then
 
575
         Begin
 
576
           Message(asmr_e_invalid_or_missing_opcode);
 
577
           RecoverConsume(true);
 
578
           exit;
 
579
         end;
 
580
        { Fill the instr object with the current state }
 
581
        with instr do
 
582
          begin
 
583
            Opcode:=ActOpcode;
 
584
            condition:=ActCondition;
 
585
          end;
 
586
 
 
587
        { We are reading operands, so opcode will be an AS_ID }
 
588
        operandnum:=1;
 
589
        Consume(AS_OPCODE);
 
590
        { Zero operand opcode ?  }
 
591
        if actasmtoken in [AS_SEPARATOR,AS_END] then
 
592
         begin
 
593
           operandnum:=0;
 
594
           exit;
 
595
         end;
 
596
        { Read the operands }
 
597
        repeat
 
598
          case actasmtoken of
 
599
            AS_COMMA: { Operand delimiter }
 
600
              Begin
 
601
                if operandnum>Max_Operands then
 
602
                  Message(asmr_e_too_many_operands)
 
603
                else
 
604
                  begin
 
605
                    { condition operands doesn't set the operand but write to the
 
606
                      condition field of the instruction
 
607
                    }
 
608
                    if instr.Operands[operandnum].opr.typ<>OPR_NONE then
 
609
                      Inc(operandnum);
 
610
                  end;
 
611
                Consume(AS_COMMA);
 
612
              end;
 
613
            AS_SEPARATOR,
 
614
            AS_END : { End of asm operands for this opcode  }
 
615
              begin
 
616
                break;
 
617
              end;
 
618
          else
 
619
            BuildOperand(instr.Operands[operandnum] as tppcoperand);
 
620
          end; { end case }
 
621
        until false;
 
622
        if (operandnum=1) and (instr.Operands[operandnum].opr.typ=OPR_NONE) then
 
623
          dec(operandnum);
 
624
        instr.Ops:=operandnum;
 
625
      end;
 
626
 
 
627
 
 
628
    function tppcattreader.is_asmopcode(const s: string):boolean;
 
629
      var
 
630
        cond  : tasmcondflag;
 
631
        hs : string;
 
632
 
 
633
      Begin
 
634
        { making s a value parameter would break other assembler readers }
 
635
        hs:=s;
 
636
        is_asmopcode:=false;
 
637
 
 
638
        { clear op code }
 
639
        actopcode:=A_None;
 
640
        { clear condition }
 
641
        fillchar(actcondition,sizeof(actcondition),0);
 
642
 
 
643
        { check for direction hint }
 
644
        if hs[length(s)]='-' then
 
645
          begin
 
646
            dec(ord(hs[0]));
 
647
            actcondition.dirhint:=DH_Minus;
 
648
          end
 
649
        else if hs[length(s)]='+' then
 
650
          begin
 
651
            dec(ord(hs[0]));
 
652
            actcondition.dirhint:=DH_Plus;
 
653
          end;
 
654
        actopcode := tasmop(ptrint(iasmops.find(hs)));
 
655
        if actopcode <> A_NONE then
 
656
          begin
 
657
            if actcondition.dirhint<>DH_None then
 
658
              message1(asmr_e_unknown_opcode,actasmpattern);
 
659
            actasmtoken:=AS_OPCODE;
 
660
            is_asmopcode:=true;
 
661
            exit;
 
662
          end;
 
663
        { not found, check branch instructions }
 
664
        if hs[1]='B' then
 
665
          begin
 
666
            { we can search here without an extra table which is sorted by string length
 
667
              because we take the whole remaining string without the leading B }
 
668
            if copy(hs,length(s)-1,2)='LR' then
 
669
              begin
 
670
                actopcode := A_BCLR;
 
671
                setlength(hs,length(hs)-2)
 
672
              end
 
673
            else if copy(hs,length(s)-2,3)='CTR' then
 
674
              begin
 
675
                actopcode := A_BCCTR;
 
676
                setlength(hs,length(hs)-3)
 
677
              end
 
678
            else
 
679
              actopcode := A_BC;
 
680
            for cond:=low(TAsmCondFlag) to high(TAsmCondFlag) do
 
681
              if copy(hs,2,length(s)-1)=UpperAsmCondFlag2Str[cond] then
 
682
                begin
 
683
                  actcondition.simple:=true;
 
684
                  actcondition.cond:=cond;
 
685
                  if (cond in [C_LT,C_LE,C_EQ,C_GE,C_GT,C_NL,C_NE,C_NG,C_SO,C_NS,C_UN,C_NU]) then
 
686
                    actcondition.cr := RS_CR0;
 
687
                  actasmtoken:=AS_OPCODE;
 
688
                  is_asmopcode:=true;
 
689
                  exit;
 
690
                end;
 
691
          end;
 
692
      end;
 
693
 
 
694
    procedure tppcattreader.ConvertCalljmp(instr : tppcinstruction);
 
695
      begin
 
696
        if instr.Operands[1].opr.typ = OPR_CONSTANT then
 
697
          begin
 
698
            if (instr.operands[1].opr.val > 31) or
 
699
               (instr.operands[2].opr.typ <> OPR_CONSTANT) or
 
700
               (instr.operands[2].opr.val > 31) or
 
701
               not(instr.operands[3].opr.typ in [OPR_REFERENCE,OPR_SYMBOL]) then
 
702
              Message(asmr_e_syn_operand);
 
703
            { BO/BI notation }
 
704
            instr.condition.simple := false;
 
705
            instr.condition.bo := instr.operands[1].opr.val;
 
706
            instr.condition.bi := instr.operands[2].opr.val;
 
707
            instr.operands[1].free;
 
708
            instr.operands[2].free;
 
709
            instr.operands[2] := nil;
 
710
            instr.operands[1] := instr.operands[3];
 
711
            instr.operands[3] := nil;
 
712
            instr.ops := 1;
 
713
          end;
 
714
        if instr.Operands[1].opr.typ = OPR_REFERENCE then
 
715
          begin
 
716
            instr.Operands[1].opr.ref.refaddr:=addr_full;
 
717
            if (instr.Operands[1].opr.ref.base<>NR_NO) or
 
718
               (instr.Operands[1].opr.ref.index<>NR_NO) then
 
719
              Message(asmr_e_syn_operand);
 
720
          end;
 
721
      end;
 
722
 
 
723
 
 
724
    procedure tppcattreader.handleopcode;
 
725
      var
 
726
        instr : tppcinstruction;
 
727
      begin
 
728
        instr:=TPPCInstruction.Create(TPPCOperand);
 
729
        BuildOpcode(instr);
 
730
        instr.condition := actcondition;
 
731
        if is_calljmp(instr.opcode) then
 
732
          ConvertCalljmp(instr);
 
733
        {
 
734
        instr.AddReferenceSizes;
 
735
        instr.SetInstructionOpsize;
 
736
        instr.CheckOperandSizes;
 
737
        }
 
738
        instr.ConcatInstruction(curlist);
 
739
        instr.Free;
 
740
      end;
 
741
 
 
742
 
 
743
{*****************************************************************************
 
744
                                     Initialize
 
745
*****************************************************************************}
 
746
 
 
747
const
 
748
  asmmode_ppc_att_info : tasmmodeinfo =
 
749
          (
 
750
            id    : asmmode_ppc_gas;
 
751
            idtxt : 'GAS';
 
752
            casmreader : tppcattreader;
 
753
          );
 
754
 
 
755
  asmmode_ppc_standard_info : tasmmodeinfo =
 
756
          (
 
757
            id    : asmmode_standard;
 
758
            idtxt : 'STANDARD';
 
759
            casmreader : tppcattreader;
 
760
          );
 
761
 
 
762
initialization
 
763
  RegisterAsmMode(asmmode_ppc_att_info);
 
764
  RegisterAsmMode(asmmode_ppc_standard_info);
 
765
end.