Просмотр исходного кода

+ support conditions in the Z80 inline assembler

git-svn-id: branches/z80@44885 -
nickysn 5 лет назад
Родитель
Сommit
a6e72713ad
2 измененных файлов с 53 добавлено и 10 удалено
  1. 9 8
      compiler/z80/agsdasz80.pas
  2. 44 2
      compiler/z80/raz80asm.pas

+ 9 - 8
compiler/z80/agsdasz80.pas

@@ -294,17 +294,18 @@ unit agsdasz80;
         i: Integer;
       begin
         writer.AsmWrite(#9#9+std_op2str[hp.opcode]);
-        if taicpu(hp).ops<>0 then
+        if (taicpu(hp).ops<>0) or (hp.condition<>C_None) then
           begin
+            writer.AsmWrite(#9);
+            if hp.condition<>C_None then
+              begin
+                writer.AsmWrite(uppercond2str[hp.condition]);
+                if taicpu(hp).ops<>0 then
+                  writer.AsmWrite(',');
+              end;
             for i:=0 to taicpu(hp).ops-1 do
               begin
-                if i=0 then
-                  begin
-                    writer.AsmWrite(#9);
-                    if hp.is_jmp and (hp.condition<>C_None) then
-                      writer.AsmWrite(uppercond2str[hp.condition]+',');
-                  end
-                else
+                if i<>0 then
                   writer.AsmWrite(',');
                 if is_calljmp(hp.opcode) then
                   WriteOper_jmp(taicpu(hp).oper[i]^,hp)

+ 44 - 2
compiler/z80/raz80asm.pas

@@ -36,7 +36,7 @@ Unit raz80asm;
         AS_NONE,AS_LABEL,AS_LLABEL,AS_STRING,AS_INTNUM,
         AS_REALNUM,AS_COMMA,AS_LPAREN,
         AS_RPAREN,AS_COLON,AS_DOT,AS_PLUS,AS_MINUS,AS_STAR,
-        AS_SEPARATOR,AS_ID,AS_REGISTER,AS_OPCODE,AS_SLASH,AS_DOLLAR,
+        AS_SEPARATOR,AS_ID,AS_REGISTER,AS_OPCODE,AS_CONDITION,AS_SLASH,AS_DOLLAR,
         AS_HASH,AS_LSBRACKET,AS_RSBRACKET,AS_LBRACKET,AS_RBRACKET,
         AS_EQUAL,
         {------------------ Assembler directives --------------------}
@@ -58,7 +58,7 @@ Unit raz80asm;
         '','Label','LLabel','string','integer',
         'float',',','(',
         ')',':','.','+','-','*',
-        ';','identifier','register','opcode','/','$',
+        ';','identifier','register','opcode','condition','/','$',
         '#','{','}','[',']',
         '=',
         'defb','defw','END',
@@ -88,6 +88,7 @@ Unit raz80asm;
       { tz80reader }
 
       tz80reader = class(tasmreader)
+        actasmcond : TAsmCond;
         actasmpattern_origcase : string;
         actasmtoken   : tasmtoken;
         prevasmtoken  : tasmtoken;
@@ -101,6 +102,7 @@ Unit raz80asm;
         function is_asmopcode(const s: string):boolean;
         Function is_asmdirective(const s: string):boolean;
         function is_register(const s:string):boolean;
+        function is_condition(const s:string):boolean;
         function is_targetdirective(const s: string):boolean;
         procedure BuildRecordOffsetSize(const expr: string;out offset:tcgint;out size:tcgint; out mangledname: string; needvmtofs: boolean; out hastypecast: boolean);
         procedure BuildConstSymbolExpression(in_flags: tconstsymbolexpressioninputflags;out value:tcgint;out asmsym:string;out asmsymtyp:TAsmsymtype;out size:tcgint;out out_flags:tconstsymbolexpressionoutputflags);
@@ -156,8 +158,12 @@ Unit raz80asm;
         len: Integer;
         srsym : tsym;
         srsymtable : TSymtable;
+        can_be_condition : Boolean;
       begin
         c:=scanner.c;
+        { certain instructions can have a condition, as an operand. We need to set this flag,
+          because 'C' can be either a register, or a condition, depending on the context }
+        can_be_condition:=(actasmtoken=AS_OPCODE) and (actopcode in [A_JP,A_JR,A_CALL,A_RET]);
         { save old token and reset new token }
         prevasmtoken:=actasmtoken;
         actasmtoken:=AS_NONE;
@@ -313,6 +319,11 @@ Unit raz80asm;
                       actasmtoken:=AS_VMTOFFSET;
                       exit;
                     end;
+                  if can_be_condition and is_condition(actasmpattern) then
+                    begin
+                      actasmtoken:=AS_CONDITION;
+                      exit;
+                    end;
                   if is_register(actasmpattern) then
                     begin
                       actasmtoken:=AS_REGISTER;
@@ -942,6 +953,25 @@ Unit raz80asm;
       end;
 
 
+    function tz80reader.is_condition(const s: string): boolean;
+      var
+        condstr: string;
+        cond: TAsmCond;
+      begin
+        is_condition:=false;
+        actasmcond:=C_None;
+        condstr:=lower(s);
+        for cond in TAsmCond do
+          if (cond<>C_None) and (cond2str[cond]=condstr) then
+            begin
+              is_condition:=true;
+              actasmtoken:=AS_CONDITION;
+              actasmcond:=cond;
+              exit;
+            end;
+      end;
+
+
     function tz80reader.is_targetdirective(const s: string): boolean;
       begin
         result:=false;
@@ -2197,6 +2227,18 @@ Unit raz80asm;
             AS_SEPARATOR :
               break;
 
+            { Condition (e.g. 'NC' in 'JP NC, label') }
+            AS_CONDITION:
+              begin
+                instr.condition:=actasmcond;
+                Consume(AS_CONDITION);
+                if actasmtoken=AS_COMMA then
+                  Consume(AS_COMMA);
+                { Zero operand opcode ?  }
+                if actasmtoken in [AS_SEPARATOR,AS_END] then
+                  exit;
+              end;
+
             { Operand delimiter }
             AS_COMMA :
               begin