Browse Source

m68k: more work on instruction validation for the internal assembler

Karoly Balogh 2 years ago
parent
commit
2cc8cf98f0
1 changed files with 69 additions and 2 deletions
  1. 69 2
      compiler/m68k/aasmcpu.pas

+ 69 - 2
compiler/m68k/aasmcpu.pas

@@ -138,6 +138,8 @@ const
 type
 type
   toperandtypeset = set of toperandtype;
   toperandtypeset = set of toperandtype;
   toperandflagset = set of toperandflags;
   toperandflagset = set of toperandflags;
+  topsupportedset = set of topsupported;
+  topsizeflagset  = set of topsizeflag;
 
 
 type
 type
   tinsentry = record
   tinsentry = record
@@ -147,8 +149,8 @@ type
     opflags  : array[0..max_operands-1] of toperandflagset;
     opflags  : array[0..max_operands-1] of toperandflagset;
     codelen  : byte;
     codelen  : byte;
     code     : array[0..1] of word;
     code     : array[0..1] of word;
-    support  : set of topsupported;
-    sizes    : set of topsizeflag;
+    support  : topsupportedset;
+    sizes    : topsizeflagset;
   end;
   end;
   pinsentry = ^tinsentry;
   pinsentry = ^tinsentry;
 
 
@@ -701,6 +703,63 @@ type
 
 
     function taicpu.Matches(p: PInsEntry; objdata:TObjData): boolean;
     function taicpu.Matches(p: PInsEntry; objdata:TObjData): boolean;
 
 
+      function TargetMatch: boolean;
+        const
+          CPUTypeToOpSupported: array[TCPUtype] of topsupportedset = (
+              {* cpu_none *}     [],
+              {* cpu_MC68000 *}  [OS_M68000,OS_M68000UP],
+              {* cpu_MC68020 *}  [OS_M68020,OS_M68000UP,OS_M68010UP,OS_M68020UP,OS_M68851],
+              {* cpu_MC68040 *}  [OS_M68040,OS_M68000UP,OS_M68010UP,OS_M68020UP,OS_M68040UP],
+              {* cpu_MC68060 *}  [OS_M68060,OS_M68000UP,OS_M68010UP,OS_M68020UP,OS_M68040UP],
+              {* cpu_isa_a *}    [OS_CF,OS_CF_ISA_A],
+              {* cpu_isa_a_p *}  [OS_CF,OS_CF_ISA_APL],
+              {* cpu_isa_b *}    [OS_CF,OS_CF_ISA_B],
+              {* cpu_isa_c *}    [OS_CF,OS_CF_ISA_C],
+              {* cpu_cfv4e *}    [OS_CF,OS_CF_ISA_B]
+          );
+          FPUTypeToOpSupported: array[TFPUtype] of topsupportedset = (
+              {* fpu_none *}     [],
+              {* fpu_soft *}     [],
+              {* fpu_libgcc *}   [],
+              {* fpu_68881 *}    [OS_M68881],
+              {* fpu_68040 *}    [OS_M68881,OS_M68040,OS_M68040UP],
+              {* fpu_68060 *}    [OS_M68881,OS_M68040,OS_M68040UP,OS_M68060],
+              {* fpu_coldfire *} [OS_CF_FPU]
+          );
+        begin
+          result:=((CPUTypeToOpSupported[current_settings.cputype] * p^.support) <> []) or
+                  ((FPUTypeToOpSupported[current_settings.fputype] * p^.support) <> []);
+        end;
+
+      function OpsizeMatch: boolean;
+        const
+          TOpSizeToOpSizeFlag: array[TOpSize] of TOpSizeFlagSet = (
+              { S_NO } [ OPS_UNSIZED],
+              { S_B  } [ OPS_SHORT, OPS_BYTE ],
+              { S_W  } [ OPS_WORD ],
+              { S_L  } [ OPS_LONG ],
+              { S_FS } [ OPS_SINGLE ],
+              { S_FD } [ OPS_DOUBLE ],
+              { S_FX } [ OPS_EXTENDED ]
+          );
+        begin
+          result:=(TOpSizeToOpSizeFlag[opsize] * p^.sizes) <> [];
+
+          { Special handling for instructions where the size can be
+            implicitly determined, because only one size is possible. }
+          if not result and (opsize in [S_NO]) then
+            begin
+              result:=(p^.sizes <> []) and (
+                 { if OPS_SHORT is in sizes, it means we have a branch
+                   instruction, so let unsized pass. }
+                 (OPS_SHORT in p^.sizes) or
+                 { Or only one size is possible. }
+                 ((p^.sizes - [ OPS_BYTE ]) = []) or
+                 ((p^.sizes - [ OPS_WORD ]) = []) or
+                 ((p^.sizes - [ OPS_LONG ]) = []));
+            end;
+        end;
+
       function OperandsMatch(const oper: toper; const ots: toperandtypeset): boolean;
       function OperandsMatch(const oper: toper; const ots: toperandtypeset): boolean;
         var
         var
           ot: toperandtype;
           ot: toperandtype;
@@ -786,6 +845,14 @@ type
         if (p^.opcode<>opcode) or (p^.ops<>ops) then
         if (p^.opcode<>opcode) or (p^.ops<>ops) then
           exit;
           exit;
 
 
+        { Check if opcode is valid for this target }
+        if not TargetMatch then
+          exit;
+
+        { Check if opcode size is valid }
+        if not OpsizeMatch then
+          exit;
+
         { Check the operands }
         { Check the operands }
         for i:=0 to p^.ops-1 do
         for i:=0 to p^.ops-1 do
           if not OperandsMatch(oper[i]^,p^.optypes[i]) then
           if not OperandsMatch(oper[i]^,p^.optypes[i]) then