Explorar el Código

+ allow segment override prefixes to be used as a standalone opcode in the intel
syntax inline assembler; this is TP7 compatible and allows compiling ugly
code, such as 'seges; db $67,$66; lodsw'

git-svn-id: trunk@38096 -

nickysn hace 7 años
padre
commit
1f0e311fdd
Se han modificado 4 ficheros con 295 adiciones y 5 borrados
  1. 1 0
      .gitattributes
  2. 21 0
      compiler/x86/agx86nsm.pas
  3. 23 5
      compiler/x86/rax86int.pas
  4. 250 0
      tests/test/tasm16.pp

+ 1 - 0
.gitattributes

@@ -12488,6 +12488,7 @@ tests/test/tasm14e.pp svneol=native#text/plain
 tests/test/tasm14f.pp svneol=native#text/plain
 tests/test/tasm15.pp svneol=native#text/plain
 tests/test/tasm15a.pp svneol=native#text/plain
+tests/test/tasm16.pp svneol=native#text/plain
 tests/test/tasm2.inc svneol=native#text/plain
 tests/test/tasm2.pp svneol=native#text/plain
 tests/test/tasm2a.pp svneol=native#text/plain

+ 21 - 0
compiler/x86/agx86nsm.pas

@@ -1086,6 +1086,27 @@ interface
                          internalerror(2017111001);
                      end;
                    end
+                  else if (fixed_opcode=A_SEGCS) or (fixed_opcode=A_SEGDS) or
+                          (fixed_opcode=A_SEGSS) or (fixed_opcode=A_SEGES) or
+                          (fixed_opcode=A_SEGFS) or (fixed_opcode=A_SEGGS) then
+                    begin
+                      case fixed_opcode of
+                        A_SEGCS:
+                          writer.AsmWrite(#9#9'cs');
+                        A_SEGDS:
+                          writer.AsmWrite(#9#9'ds');
+                        A_SEGSS:
+                          writer.AsmWrite(#9#9'ss');
+                        A_SEGES:
+                          writer.AsmWrite(#9#9'es');
+                        A_SEGFS:
+                          writer.AsmWrite(#9#9'fs');
+                        A_SEGGS:
+                          writer.AsmWrite(#9#9'gs');
+                        else
+                          internalerror(2018020101);
+                      end;
+                    end
                   else
                     writer.AsmWrite(#9#9+prefix+std_op2str[fixed_opcode]+cond2str[taicpu(hp).condition]);
                   if taicpu(hp).ops<>0 then

+ 23 - 5
compiler/x86/rax86int.pas

@@ -2116,6 +2116,7 @@ Unit Rax86int;
         i:byte;
         tmp: toperand;
         di_param, si_param: ShortInt;
+        prefix_or_override_pending_concat: boolean = false;
 {$ifdef i8086}
         hsymbol: TAsmSymbol;
         hoffset: ASizeInt;
@@ -2130,22 +2131,26 @@ Unit Rax86int;
           if is_prefix(actopcode) then
             with instr do
               begin
+                if prefix_or_override_pending_concat then
+                  ConcatInstruction(curlist);
                 PrefixOp:=ActOpcode;
                 opcode:=ActOpcode;
                 condition:=ActCondition;
                 opsize:=ActOpsize;
-                ConcatInstruction(curlist);
+                prefix_or_override_pending_concat:=true;
                 consume(AS_OPCODE);
               end
           else
            if is_override(actopcode) then
              with instr do
                begin
+                 if prefix_or_override_pending_concat then
+                   ConcatInstruction(curlist);
                  OverrideOp:=ActOpcode;
                  opcode:=ActOpcode;
                  condition:=ActCondition;
                  opsize:=ActOpsize;
-                 ConcatInstruction(curlist);
+                 prefix_or_override_pending_concat:=true;
                  consume(AS_OPCODE);
                end
           else
@@ -2157,10 +2162,23 @@ Unit Rax86int;
         { opcode }
         if (actasmtoken <> AS_OPCODE) then
          begin
-           Message(asmr_e_invalid_or_missing_opcode);
-           RecoverConsume(false);
-           exit;
+           { allow a prefix or override to be used standalone, like an opcode
+             with zero operands; this is TP7 compatible and allows compiling
+             ugly code like 'seges; db $67,$66; lodsw' }
+           if prefix_or_override_pending_concat then
+             exit
+           else
+             begin
+               Message(asmr_e_invalid_or_missing_opcode);
+               RecoverConsume(false);
+               exit;
+             end;
          end;
+        if prefix_or_override_pending_concat then
+          begin
+            instr.ConcatInstruction(curlist);
+            prefix_or_override_pending_concat:=false;
+          end;
         { Fill the instr object with the current state }
         with instr do
           begin

+ 250 - 0
tests/test/tasm16.pp

@@ -0,0 +1,250 @@
+{ %CPU=i8086,i386,x86_64 }
+
+program tasm16;
+
+{$ifdef cpui8086}
+{$asmcpu 80386}
+{$endif cpui8086}
+
+const
+{$ifdef cpui8086}
+  expect1: array [0..3] of byte = (
+    $2E,              // segcs
+    $67,$66,          // db $67,$66
+    $AD               // lodsw
+  );
+  expect2: array [0..3] of byte = (
+    $3E,              // segds
+    $67,$66,          // db $67,$66
+    $AD               // lodsw
+  );
+  expect3: array [0..3] of byte = (
+    $36,              // segss
+    $67,$66,          // db $67,$66
+    $AD               // lodsw
+  );
+  expect4: array [0..3] of byte = (
+    $26,              // seges
+    $67,$66,          // db $67,$66
+    $AD               // lodsw
+  );
+  expect5: array [0..3] of byte = (
+    $64,              // segfs
+    $67,$66,          // db $67,$66
+    $AD               // lodsw
+  );
+  expect6: array [0..3] of byte = (
+    $65,              // seggs
+    $67,$66,          // db $67,$66
+    $AD               // lodsw
+  );
+{$else}
+  expect1: array [0..4] of byte = (
+    $2E,              // segcs
+    $67,$66,          // db $67,$66
+    $66,$AD           // lodsw
+  );
+  expect2: array [0..4] of byte = (
+    $3E,              // segds
+    $67,$66,          // db $67,$66
+    $66,$AD           // lodsw
+  );
+  expect3: array [0..4] of byte = (
+    $36,              // segss
+    $67,$66,          // db $67,$66
+    $66,$AD           // lodsw
+  );
+  expect4: array [0..4] of byte = (
+    $26,              // seges
+    $67,$66,          // db $67,$66
+    $66,$AD           // lodsw
+  );
+  expect5: array [0..4] of byte = (
+    $64,              // segfs
+    $67,$66,          // db $67,$66
+    $66,$AD           // lodsw
+  );
+  expect6: array [0..4] of byte = (
+    $65,              // seggs
+    $67,$66,          // db $67,$66
+    $66,$AD           // lodsw
+  );
+{$endif}
+  expect7: array [0..0] of byte = (
+    $2E               // segcs
+  );
+  expect8: array [0..0] of byte = (
+    $3E               // segds
+  );
+  expect9: array [0..0] of byte = (
+    $36               // segss
+  );
+  expect10: array [0..0] of byte = (
+    $26               // seges
+  );
+  expect11: array [0..0] of byte = (
+    $64               // segfs
+  );
+  expect12: array [0..0] of byte = (
+    $65               // seggs
+  );
+  expect13: array [0..1] of byte = (
+    $2E,$AC           // segcs lodsb
+  );
+  expect14: array [0..1] of byte = (
+    $3E,$AC           // segds lodsb
+  );
+  expect15: array [0..1] of byte = (
+    $36,$AC           // segss lodsb
+  );
+  expect16: array [0..1] of byte = (
+    $26,$AC           // seges lodsb
+  );
+  expect17: array [0..1] of byte = (
+    $64,$AC           // segfs lodsb
+  );
+  expect18: array [0..1] of byte = (
+    $65,$AC           // seggs lodsb
+  );
+
+{$asmmode intel}
+
+procedure test1; assembler; nostackframe;
+asm
+  segcs; db $67,$66; lodsw
+end;
+procedure test2; assembler; nostackframe;
+asm
+  segds; db $67,$66; lodsw
+end;
+procedure test3; assembler; nostackframe;
+asm
+  segss; db $67,$66; lodsw
+end;
+procedure test4; assembler; nostackframe;
+asm
+  seges; db $67,$66; lodsw
+end;
+procedure test5; assembler; nostackframe;
+asm
+  segfs; db $67,$66; lodsw
+end;
+procedure test6; assembler; nostackframe;
+asm
+  seggs; db $67,$66; lodsw
+end;
+procedure test7; assembler; nostackframe;
+asm
+  segcs
+end;
+procedure test8; assembler; nostackframe;
+asm
+  segds
+end;
+procedure test9; assembler; nostackframe;
+asm
+  segss
+end;
+procedure test10; assembler; nostackframe;
+asm
+  seges
+end;
+procedure test11; assembler; nostackframe;
+asm
+  segfs
+end;
+procedure test12; assembler; nostackframe;
+asm
+  seggs
+end;
+procedure test13; assembler; nostackframe;
+asm
+  segcs lodsb
+end;
+procedure test14; assembler; nostackframe;
+asm
+  segds lodsb
+end;
+procedure test15; assembler; nostackframe;
+asm
+  segss lodsb
+end;
+procedure test16; assembler; nostackframe;
+asm
+  seges lodsb
+end;
+procedure test17; assembler; nostackframe;
+asm
+  segfs lodsb
+end;
+procedure test18; assembler; nostackframe;
+asm
+  seggs lodsb
+end;
+
+procedure Error;
+begin
+  Writeln('Error!');
+  Halt(1);
+end;
+
+{$ifdef cpui8086}
+{ This version works in all i8086 memory models }
+function CompareCode(cp: CodePointer; dp: Pointer; sz: SizeInt): Boolean;
+var
+  I: SizeInt;
+begin
+  for I := 0 to sz - 1 do
+    if Mem[Seg(cp^):Ofs(cp^) + I] <> Mem[Seg(dp^):Ofs(dp^) + I] then
+    begin
+      CompareCode := False;
+      exit;
+    end;
+  CompareCode := True;
+end;
+{$else cpui8086}
+function CompareCode(cp: CodePointer; dp: Pointer; sz: SizeInt): Boolean;
+begin
+  CompareCode := CompareByte(cp^, dp^, sz) = 0;
+end;
+{$endif}
+
+begin
+  if not CompareCode(CodePointer(@test1), @expect1, SizeOf(expect1)) then
+    Error;
+  if not CompareCode(CodePointer(@test2), @expect2, SizeOf(expect2)) then
+    Error;
+  if not CompareCode(CodePointer(@test3), @expect3, SizeOf(expect3)) then
+    Error;
+  if not CompareCode(CodePointer(@test4), @expect4, SizeOf(expect4)) then
+    Error;
+  if not CompareCode(CodePointer(@test5), @expect5, SizeOf(expect5)) then
+    Error;
+  if not CompareCode(CodePointer(@test6), @expect6, SizeOf(expect6)) then
+    Error;
+  if not CompareCode(CodePointer(@test7), @expect7, SizeOf(expect7)) then
+    Error;
+  if not CompareCode(CodePointer(@test8), @expect8, SizeOf(expect8)) then
+    Error;
+  if not CompareCode(CodePointer(@test9), @expect9, SizeOf(expect9)) then
+    Error;
+  if not CompareCode(CodePointer(@test10), @expect10, SizeOf(expect10)) then
+    Error;
+  if not CompareCode(CodePointer(@test11), @expect11, SizeOf(expect11)) then
+    Error;
+  if not CompareCode(CodePointer(@test12), @expect12, SizeOf(expect12)) then
+    Error;
+  if not CompareCode(CodePointer(@test13), @expect13, SizeOf(expect13)) then
+    Error;
+  if not CompareCode(CodePointer(@test14), @expect14, SizeOf(expect14)) then
+    Error;
+  if not CompareCode(CodePointer(@test15), @expect15, SizeOf(expect15)) then
+    Error;
+  if not CompareCode(CodePointer(@test16), @expect16, SizeOf(expect16)) then
+    Error;
+  if not CompareCode(CodePointer(@test17), @expect17, SizeOf(expect17)) then
+    Error;
+  if not CompareCode(CodePointer(@test18), @expect18, SizeOf(expect18)) then
+    Error;
+  Writeln('Ok!')
+end.