Преглед изворни кода

+ support labels in the Z80 inline assembler

git-svn-id: branches/z80@44883 -
nickysn пре 5 година
родитељ
комит
90fa75fb7a
1 измењених фајлова са 174 додато и 1 уклоњено
  1. 174 1
      compiler/z80/raz80asm.pas

+ 174 - 1
compiler/z80/raz80asm.pas

@@ -88,6 +88,7 @@ Unit raz80asm;
       { tz80reader }
 
       tz80reader = class(tasmreader)
+        actasmpattern_origcase : string;
         actasmtoken   : tasmtoken;
         prevasmtoken  : tasmtoken;
         inexpression : boolean;
@@ -217,6 +218,7 @@ Unit raz80asm;
                 c:=current_scanner.asmgetchar;
               end;
             actasmpattern[0]:=chr(len);
+            actasmpattern_origcase:=actasmpattern;
             { Label ? }
             if c = ':' then
               begin
@@ -286,6 +288,7 @@ Unit raz80asm;
                      c:=current_scanner.asmgetchar;
                    end;
                   actasmpattern[0]:=chr(len);
+                  actasmpattern_origcase:=actasmpattern;
                   uppervar(actasmpattern);
  {$ifdef x86}
                   { only x86 architectures have instruction prefixes }
@@ -1944,9 +1947,28 @@ Unit raz80asm;
 
 
     procedure tz80reader.BuildOperand(oper: tz80operand; istypecast: boolean);
+
+      procedure AddLabelOperand(hl:tasmlabel);
+      begin
+        if (oper.opr.typ=OPR_NONE) and
+           is_calljmp(actopcode) then
+         begin
+           oper.opr.typ:=OPR_SYMBOL;
+           oper.opr.symbol:=hl;
+         end
+        else
+         begin
+           oper.InitRef;
+           oper.opr.ref.symbol:=hl;
+           oper.haslabelref:=true;
+         end;
+      end;
+
       var
-        l: LongInt;
+        l: tcgint;
         tsize: tcgint;
+        expr: string;
+        hl: tasmlabel;
       begin
         repeat
           case actasmtoken of
@@ -1990,6 +2012,142 @@ Unit raz80asm;
                 BuildReference(oper);
               end;
 
+            AS_ID : { A constant expression, or a Variable ref. }
+              Begin
+                { Label or Special symbol reference? }
+                if actasmpattern[1] = '@' then
+                 Begin
+                   if actasmpattern = '@RESULT' then
+                    Begin
+                      oper.SetupResult;
+                      Consume(AS_ID);
+                      expr:='result';
+                    end
+                   else
+                    if (actasmpattern = '@CODE') or (actasmpattern = '@DATA') then
+                     begin
+                       Message(asmr_w_CODE_and_DATA_not_supported);
+                       Consume(AS_ID);
+                     end
+                   else
+                    { Local Label }
+                    begin
+                      CreateLocalLabel(actasmpattern,hl,false);
+                      Consume(AS_ID);
+                      AddLabelOperand(hl);
+                    end;
+                 end
+                else
+                { support result for delphi modes }
+                 if (m_objpas in current_settings.modeswitches) and (actasmpattern='RESULT') then
+                  begin
+                    oper.SetUpResult;
+                    Consume(AS_ID);
+                    expr:='result';
+                  end
+                { probably a variable or normal expression }
+                { or a procedure (such as in CALL ID)      }
+                else
+                 Begin
+                   { is it a constant ? }
+                   if SearchIConstant(actasmpattern,l) then
+                    Begin
+                      case oper.opr.typ of
+                        OPR_REFERENCE :
+                          begin
+                            l := BuildRefConstExpression(tsize);
+                            if tsize<>0 then
+                              oper.SetSize(tsize,false);
+                            inc(oper.opr.ref.offset,l);
+                            inc(oper.opr.constoffset,l);
+                          end;
+
+                        OPR_LOCAL :
+                          begin
+                            l := BuildRefConstExpression(tsize);
+                            if tsize<>0 then
+                              oper.SetSize(tsize,false);
+                            inc(oper.opr.localsymofs,l);
+                            inc(oper.opr.localconstoffset,l);
+                          end;
+                        OPR_NONE,
+                        OPR_CONSTANT :
+                          BuildConstantOperand(oper);
+                        else
+                          Message(asmr_e_invalid_operand_type);
+                      end;
+                    end
+                   else
+                    { Check for pascal label }
+                    if SearchLabel(actasmpattern,hl,false) then
+                     begin
+                       Consume(AS_ID);
+                       AddLabelOperand(hl);
+                     end
+                    else
+                    { is it a normal variable ? }
+                     Begin
+                       expr:=actasmpattern;
+                       Consume(AS_ID);
+
+
+                       { typecasting? }
+                       if SearchType(expr,l) then
+                        begin
+                          oper.hastype:=true;
+                          oper.typesize:=l;
+                          case actasmtoken of
+                            AS_LPAREN :
+                              begin
+                                { Support Type([Reference]) }
+                                Consume(AS_LPAREN);
+                                BuildOperand(oper,true);
+                                { Delphi also supports Type(Register) and
+                                  interprets it the same as Type([Register]).  }
+                                if (oper.opr.typ = OPR_REGISTER) then
+                                  { This also sets base to the register.  }
+                                  oper.InitRef;
+                                Consume(AS_RPAREN);
+                              end;
+                            //AS_LBRACKET :
+                            //  begin
+                            //    { Support Var.Type[Index] }
+                            //    { Convert @label.Byte[1] to reference }
+                            //    if oper.opr.typ=OPR_SYMBOL then
+                            //      oper.initref;
+                            //  end;
+                            else
+                              ;
+                          end;
+                        end
+                       else
+                        begin
+                          if not oper.SetupVar(expr,false) then
+                            Begin
+                              { not a variable, check special variables.. }
+                              if expr = 'SELF' then
+                                begin
+                                  oper.SetupSelf;
+                                  expr:='self';
+                                end
+                              else
+                                begin
+                                  Message1(sym_e_unknown_id,expr);
+                                  expr:='';
+                                end;
+                            end;
+                          { indexed access to variable? }
+                          //if actasmtoken=AS_LBRACKET then
+                          //  begin
+                          //    { ... then the operand size is not known anymore }
+                          //    oper.size:=OS_NO;
+                          //    BuildReference(oper);
+                          //  end;
+                        end;
+                     end;
+                 end;
+              end;
+
             AS_REGISTER : { Register, a variable reference or a constant reference }
               begin
                 Consume(AS_REGISTER);
@@ -2094,6 +2252,8 @@ Unit raz80asm;
 
 
     function tz80reader.Assemble: tlinkedlist;
+      var
+        hl: tasmlabel;
       begin
         Message1(asmr_d_start_reading,'Z80');
         firsttoken:=TRUE;
@@ -2114,6 +2274,19 @@ Unit raz80asm;
         { main loop }
         repeat
           case actasmtoken of
+            AS_LABEL:
+              Begin
+                if SearchLabel(upper(actasmpattern),hl,true) then
+                  begin
+                    if hl.is_public then
+                      ConcatPublic(curlist,actasmpattern_origcase);
+                    ConcatLabel(curlist,hl);
+                  end
+                else
+                 Message1(asmr_e_unknown_label_identifier,actasmpattern);
+                Consume(AS_LABEL);
+              end;
+
             AS_END:
               begin
                 break; { end assembly block }