فهرست منبع

+ when compiling for Darwin/ARM, pass the subarchitecture to the linker.
The old linker option to accept object files from all subarchitecture
types no longer works.
+ support for subarchitectures in fcl-res/fpcres

git-svn-id: trunk@18070 -

Jonas Maebe 14 سال پیش
والد
کامیت
ec8c7b4888

+ 13 - 5
compiler/comprsrc.pas

@@ -75,7 +75,7 @@ implementation
 uses
   SysUtils,
   cutils,cfileutl,cclasses,
-  Globtype,Globals,Verbose,Fmodule, comphook;
+  Globtype,Globals,Verbose,Fmodule, comphook,cpuinfo;
 
 {****************************************************************************
                               TRESOURCEFILE
@@ -237,7 +237,8 @@ var
   srcfilepath,
   preprocessorbin,
   s : TCmdStr;
-  arch : ansistring;
+  arch,
+  subarch: ansistring;
 
   function WindresFileName(filename: TCmdStr): TCmdStr;
   // to be on the safe side, for files that are passed to the preprocessor,
@@ -271,11 +272,18 @@ begin
       else
         ObjUsed:=(pos('$OBJ',s)>0);
       Replace(s,'$OBJ',maybequoted(OutName));
+      subarch:='all';
       arch:=cpu2str[target_cpu];
-      //Differentiate between arm and armeb
-      if (source_info.cpu=cpu_arm) and (source_info.endian=endian_big) then
-        arch:=arch+'eb';
+      if (source_info.cpu=systems.cpu_arm) then
+        begin
+          //Differentiate between arm and armeb
+          if (source_info.endian=endian_big) then
+            arch:=arch+'eb';
+        end;
       Replace(s,'$ARCH',arch);
+      if target_info.system=system_arm_darwin then
+        subarch:=lower(cputypestr[current_settings.cputype]);
+      Replace(s,'$SUBARCH',subarch);
       case target_info.endian of
         endian_little : Replace(s,'$ENDIAN','littleendian');
         endian_big : Replace(s,'$ENDIAN','bigendian');

+ 1 - 1
compiler/systems/i_bsd.pas

@@ -37,7 +37,7 @@ unit i_bsd;
            (
              id     : res_macho;
              resbin : 'fpcres';
-             rescmd : '-o $OBJ -a $ARCH -of mach-o $DBG';
+             rescmd : '-o $OBJ -a $ARCH -s $SUBARCH -of mach-o $DBG';
              rcbin  : 'windres';
              rccmd  : '--include $INC -O res -o $RES $RC';
              resourcefileclass : nil;

+ 3 - 3
compiler/systems/t_bsd.pas

@@ -341,9 +341,9 @@ begin
             system_x86_64_darwin:
               LinkRes.Add('x86_64');
             system_arm_darwin:
-              { don't specify architecture subtype, because then CPU_SUBTYPE_ALL
-                files, such as compiled resources, are rejected }
-              LinkRes.Add('arm');
+              { current versions of the linker require the sub-architecture type
+                to be specified }
+              LinkRes.Add(lower(cputypestr[current_settings.cputype]));
           end;
       end;
   end;

+ 5 - 0
packages/fcl-res/src/machoconsts.pp

@@ -56,6 +56,11 @@ const
   CPU_SUBTYPE_X86_64_ALL  = CPU_SUBTYPE_I386_ALL;
   CPU_SUBTYPE_POWERPC_ALL = 0;
   CPU_SUBTYPE_ARM_ALL     = 0;
+  CPU_SUBTYPE_ARM_V4T     = 5;
+  CPU_SUBTYPE_ARM_V6      = 6;
+  CPU_SUBTYPE_ARM_V5TEJ   = 7;
+  CPU_SUBTYPE_ARM_XSCALE  = 8;
+  CPU_SUBTYPE_ARM_V7      = 9;
 
   //Mach-O object types
   MH_OBJECT      = $1;            // relocatable object file

+ 4 - 3
packages/fcl-res/src/machosubwriter.inc

@@ -37,7 +37,8 @@ type
     procedure FixResHeader(aStream : TStream); override;
   public
     constructor Create(aParent : TMachOResourceWriter; const aMachineType
-      : TMachOMachineType; const aOppositeEndianess : boolean); override;
+      : TMachOMachineType; const aSubMachineType: TMachoSubMachineType;
+      const aOppositeEndianess : boolean); override;
   end;
 
 { _TMachOSymbolTable_ }
@@ -336,9 +337,9 @@ begin
 end;
 
 constructor _TMachOSubWriter_.Create(aParent : TMachOResourceWriter;
-  const aMachineType : TMachOMachineType; const aOppositeEndianess : boolean);
+  const aMachineType : TMachOMachineType; const aSubMachineType: TMachoSubMachineType; const aOppositeEndianess : boolean);
 begin
-  inherited Create(aParent, aMachineType,aOppositeEndianess);
+  inherited Create(aParent,aMachineType,aSubMachineType,aOppositeEndianess);
   fSymbolTable:=_TMachOSymbolTable_.Create(fMachOStringTable);
   fSymbolTable.OppositeEndianess:=fOppositeEndianess;
   {$IF _TMachOSubWriter_=TMachO32SubWriter}

+ 5 - 0
packages/fcl-res/src/machotypes.pp

@@ -21,6 +21,11 @@ interface
 
 type
   TMachOMachineType = (mmtpowerpc, mmtpowerpc64, mmti386, mmtx86_64, mmtarm);
+  TMachOSubMachineTypePowerPC = (msmppc_all);
+  TMachOSubMachineTypePowerPC64 = (msmppc64_all);
+  TMachOSubMachineType386 = (msm386_all);
+  TMachOSubMachineTypex64 = (msmx64_all);
+  TMachOSubMachineTypeArm = (msmarm_all,msmarm_v4t,msmarm_v6,msmarm_v5tej,msmarm_xscale,msmarm_v7);
   TSegSectName = array[0..15] of char;
 
 type

+ 39 - 11
packages/fcl-res/src/machowriter.pp

@@ -30,6 +30,15 @@ type
 
   { TMachOResourceWriter }
 
+  TMachoSubMachineType = record
+    case TMachOMachineType of
+      msmppc_all: (fPpcSubType: TMachOSubMachineTypePowerPC);
+      msmppc64_all: (fPpc64SubType: TMachOSubMachineTypePowerPC64);
+      msm386_all: (f386SubType: TMachOSubMachineType386);
+      msmx64_all: (fX64SubType: TMachOSubMachineTypex64);
+      mmtarm: (fArmSubType: TMachOSubMachineTypeArm);
+  end;
+
   TMachOResourceWriter = class(TAbstractResourceWriter)
   private
     fExtensions : string;
@@ -38,10 +47,12 @@ type
     fEndianess : integer;
     fOppositeEndianess : boolean;
     fMachineType : TMachOMachineType;
+    fSubMachineType : TMachoSubMachineType;
     fBits : integer;
 
     procedure SetDefaultTarget;
     procedure SetMachineType(const aMachineType : TMachOMachineType);
+    procedure SetSubMachineType(const aSubMachineType: TMachoSubMachineType);
   protected
     function GetExtensions : string; override;
     function GetDescription : string; override;
@@ -50,6 +61,7 @@ type
     constructor Create; override;
     destructor Destroy; override;
     property MachineType : TMachOMachineType read fMachineType write SetMachineType;
+    property SubMachineType : TMachOSubMachineType read fSubMachineType write SetSubMachineType;
   end;
 
 implementation
@@ -115,6 +127,7 @@ type
     fParent : TMachOResourceWriter;
     fOppositeEndianess : boolean;
     fMachineType : TMachOMachineType;
+    fSubMachineType: TMachoSubMachineType;
     fDataAlignment : integer;
     fSectAlignment : integer;
     fSegType : longword;
@@ -154,7 +167,8 @@ type
     procedure Write(aResources: TResources; aStream: TStream);
   public
     constructor Create(aParent : TMachOResourceWriter; const aMachineType
-      : TMachOMachineType; const aOppositeEndianess : boolean); virtual;
+      : TMachOMachineType; const aSubMachineType: TMachoSubMachineType;
+      const aOppositeEndianess : boolean); virtual;
     destructor Destroy; override;
   end;
 
@@ -469,33 +483,41 @@ begin
 end;
 
 procedure TAbstractMachOSubWriter.FixHeader(aStream: TStream);
+const
+  ppcsm2int: array[TMachOSubMachineTypePowerPC] of longint = (CPU_SUBTYPE_POWERPC_ALL);
+  ppc64sm2int: array[TMachOSubMachineTypePowerPC64] of longint = (CPU_SUBTYPE_POWERPC_ALL);
+  i386sm2int: array[TMachOSubMachineType386] of longint = (CPU_SUBTYPE_I386_ALL);
+  x86_64sm2int: array[TMachOSubMachineTypex64] of longint = (CPU_SUBTYPE_X86_64_ALL);
+  armsm2int: array[TMachOSubMachineTypeArm] of longint = (CPU_SUBTYPE_ARM_ALL,
+    CPU_SUBTYPE_ARM_V4T,CPU_SUBTYPE_ARM_V6,CPU_SUBTYPE_ARM_V5TEJ,
+    CPU_SUBTYPE_ARM_XSCALE,CPU_SUBTYPE_ARM_V7);
 begin
   aStream.Position:=0;
   case fMachineType of
     mmtpowerpc   : begin
                      fHeader.magic:=MH_MAGIC;
                      fHeader.cputype:=CPU_TYPE_POWERPC;
-                     fHeader.cpusubtype:=CPU_SUBTYPE_POWERPC_ALL;
+                     fHeader.cpusubtype:=ppcsm2int[fSubMachineType.fPpcSubType];
                    end;
     mmtpowerpc64 : begin
                      fHeader.magic:=MH_MAGIC_64;
                      fHeader.cputype:=CPU_TYPE_POWERPC64;
-                     fHeader.cpusubtype:=CPU_SUBTYPE_POWERPC_ALL;
+                     fHeader.cpusubtype:=ppc64sm2int[fSubMachineType.fPpc64SubType];
                    end;
     mmti386      : begin
                      fHeader.magic:=MH_MAGIC;
                      fHeader.cputype:=CPU_TYPE_I386;
-                     fHeader.cpusubtype:=CPU_SUBTYPE_I386_ALL;
+                     fHeader.cpusubtype:=i386sm2int[fSubMachineType.f386SubType];
                    end;
     mmtx86_64    : begin
                      fHeader.magic:=MH_MAGIC_64;
                      fHeader.cputype:=CPU_TYPE_X86_64;
-                     fHeader.cpusubtype:=CPU_SUBTYPE_X86_64_ALL;
+                     fHeader.cpusubtype:=x86_64sm2int[fSubMachineType.fX64SubType];
                    end;
     mmtarm      : begin
                      fHeader.magic:=MH_MAGIC;
                      fHeader.cputype:=CPU_TYPE_ARM;
-                     fHeader.cpusubtype:=CPU_SUBTYPE_ARM_ALL;
+                     fHeader.cpusubtype:=armsm2int[fSubMachineType.fArmSubType];
                    end;
   end;
   fHeader.filetype:=MH_OBJECT;
@@ -541,10 +563,12 @@ begin
 end;
 
 constructor TAbstractMachOSubWriter.Create(aParent : TMachOResourceWriter;
-  const aMachineType : TMachOMachineType; const aOppositeEndianess : boolean);
+  const aMachineType : TMachOMachineType; const aSubMachineType:
+  TMachoSubMachineType; const aOppositeEndianess : boolean);
 begin
   fParent:=aParent;
   fMachineType:=aMachineType;
+  fSubMachineType:=aSubMachineType;
   fOppositeEndianess:=aOppositeEndianess;
   fRoot:=nil;
   fMachOStringTable:=TObjectStringTable.Create(nil,0);
@@ -570,8 +594,7 @@ begin
   {$INCLUDE machodefaulttarget.inc}
 end;
 
-procedure TMachOResourceWriter.SetMachineType(
-  const aMachineType: TMachOMachineType);
+procedure TMachOResourceWriter.SetMachineType(const aMachineType: TMachOMachineType);
 begin
   case aMachineType of
     mmtpowerpc   : begin fBits:=MACH_32BIT; fEndianess:=MACH_BIG_ENDIAN; end;
@@ -584,6 +607,11 @@ begin
   fOppositeEndianess:=fNativeEndianess<>fEndianess;
 end;
 
+procedure TMachOResourceWriter.SetSubMachineType(const aSubMachineType: TMachoSubMachineType);
+begin
+  fSubMachineType:=aSubMachineType;
+end;
+
 function TMachOResourceWriter.GetExtensions: string;
 begin
   Result:=fExtensions;
@@ -598,8 +626,8 @@ procedure TMachOResourceWriter.Write(aResources: TResources; aStream: TStream);
 var subwriter : TAbstractMachOSubWriter;
 begin
   case fBits of
-    MACH_32BIT : subwriter:=TMachO32SubWriter.Create(self,fMachineType,fOppositeEndianess);
-    MACH_64BIT : subwriter:=TMachO64SubWriter.Create(self,fMachineType,fOppositeEndianess)
+    MACH_32BIT : subwriter:=TMachO32SubWriter.Create(self,fMachineType,fSubMachineType,fOppositeEndianess);
+    MACH_64BIT : subwriter:=TMachO64SubWriter.Create(self,fMachineType,fSubMachineType,fOppositeEndianess)
   else
     raise EMachOResourceWriterUnknownBitSizeException.Create('');
   end;

+ 57 - 21
utils/fpcres/fpcres.pas

@@ -62,20 +62,23 @@ begin
   writeln('Syntax: '+progname+' [options] <inputfile> [<inputfile>...] [-o <outputfile>]');
   writeln;
   writeln('Options:');
-  writeln('  --help, -h, -?     Show this screen.');
-  writeln('  --version, -V      Show program version.');
-  writeln('  --verbose, -v      Be verbose.');
-  writeln('  --input, -i <x>    Ignored for compatibility.');
-  writeln('  --output, -o <x>   Set the output file name.');
-  writeln('  -of <format>       Set the output file format. Supported formats:');
-  writeln('                       res, elf, coff, mach-o, external');
-  writeln('  --arch, -a <name>  Set object file architecture. Supported architectures:');
-  writeln('                       i386, x86_64, arm (coff)');
-  writeln('                       i386, x86_64, powerpc, powerpc64, arm, armeb, m68k,');
-  writeln('                       sparc, alpha, ia64 (elf)');
-  writeln('                       i386, x86_64, powerpc, powerpc64 (mach-o)');
-  writeln('                       bigendian, littleendian (external)');
-  writeln('  @<file>            Read more options from file <file>');
+  writeln('  --help, -h, -?       Show this screen.');
+  writeln('  --version, -V        Show program version.');
+  writeln('  --verbose, -v        Be verbose.');
+  writeln('  --input, -i <x>      Ignored for compatibility.');
+  writeln('  --output, -o <x>     Set the output file name.');
+  writeln('  -of <format>         Set the output file format. Supported formats:');
+  writeln('                         res, elf, coff, mach-o, external');
+  writeln('  --arch, -a <name>    Set object file architecture. Supported architectures:');
+  writeln('                         i386, x86_64, arm, arm (coff)');
+  writeln('                         i386, x86_64, powerpc, powerpc64, arm, armeb, m68k,');
+  writeln('                         sparc, alpha, ia64 (elf)');
+  writeln('                         i386, x86_64, powerpc, powerpc64 (mach-o)');
+  writeln('                         bigendian, littleendian (external)');
+  writeln('  --subarch, -s <name> Set object file sub-architecture. Supported values:');
+  writeln('                         arm: all, v4t, v6, v5tej, xscale, v7');
+  writeln('                         other architectures: all');
+  writeln('  @<file>              Read more options from file <file>');
   writeln('Default output target: '+TargetToStr(currenttarget));
 end;
 
@@ -112,9 +115,16 @@ begin
   if params.Target.machine=mtNone then
   begin
     if not (CurrentTarget.machine in ObjFormats[CurrentTarget.objformat].machines) then
-      CurrentTarget.machine:=GetDefaultMachineForFormat(CurrentTarget.objformat);
+      begin
+        CurrentTarget.machine:=GetDefaultMachineForFormat(CurrentTarget.objformat);
+        CurrentTarget.submachine:=GetDefaultSubMachineForMachine(currentTarget.machine);
+      end
   end
-  else CurrentTarget.machine:=params.Target.machine;
+  else
+    begin
+      CurrentTarget.machine:=params.Target.machine;
+      CurrentTarget.submachine:=params.Target.submachine;
+    end;
 
   if not (CurrentTarget.machine in ObjFormats[CurrentTarget.objformat].machines) then
   begin
@@ -255,16 +265,42 @@ begin
 end;
 
 function SetUpMachOWriter : TMachOResourceWriter;
+const
+  ArmSubMachine2MachOSubMachine: array[TSubMachineTypeArm] of TMachOSubMachineTypeArm =
+    (msmarm_all,msmarm_v4t,msmarm_v6,msmarm_v5tej,msmarm_xscale,msmarm_v7);
+var
+  MachOSubMachineType: TMachoSubMachineType;
 begin
   Result:=TMachOResourceWriter.Create;
   case CurrentTarget.machine of
 //    mtnone :
-    mti386 : Result.MachineType:=mmti386;
-    mtx86_64 : Result.MachineType:=mmtx86_64;
-    mtppc : Result.MachineType:=mmtpowerpc;
-    mtppc64 : Result.MachineType:=mmtpowerpc64;
-    mtarm : Result.MachineType:=mmtarm;
+    mti386 :
+      begin
+        Result.MachineType:=mmti386;
+        MachOSubMachineType.f386SubType:=msm386_all;
+      end;
+    mtx86_64 :
+      begin
+        Result.MachineType:=mmtx86_64;
+        MachOSubMachineType.fX64SubType:=msmx64_all;
+      end;
+    mtppc :
+      begin
+        Result.MachineType:=mmtpowerpc;
+        MachOSubMachineType.fPpcSubType:=msmppc_all;
+      end;
+    mtppc64 :
+      begin
+        Result.MachineType:=mmtpowerpc64;
+        MachOSubMachineType.fPpc64SubType:=msmppc64_all;
+      end;
+    mtarm :
+      begin
+        Result.MachineType:=mmtarm;
+        MachOSubMachineType.fArmSubType:=ArmSubMachine2MachOSubMachine[CurrentTarget.submachine.subarm];
+      end;
   end;
+  Result.SubMachineType:=MachOSubMachineType;
 end;
 
 

+ 37 - 0
utils/fpcres/paramparser.pas

@@ -30,6 +30,7 @@ type
   EArgumentMissingException = class(EParametersException);
   EUnknownObjFormatException = class(EParametersException);
   EUnknownMachineException = class(EParametersException);
+  EUnknownSubMachineException = class(EParametersException);
   ECannotReadConfFile = class(EParametersException);
 
 type
@@ -49,6 +50,7 @@ type
     procedure ParseOutputFile(aList : TStringList; var index : integer; const parname : string);
     procedure ParseOutputFormat(aList : TStringList; var index : integer; const parname : string);
     procedure ParseArchitecture(aList : TStringList; var index : integer; const parname : string);
+    procedure ParseSubArchitecture(aList : TStringList; var index : integer; const parname : string);
     procedure ParseConfigFile(aList : TStringList; var index : integer; const parname : string);
     function DoOptionalArgument(aList : TStringList; const i : integer) : string;
     function DoMandatoryArgument(aList : TStringList; const i : integer) : string;
@@ -242,6 +244,7 @@ begin
     if Machines[aMachine].name=tmp then
     begin
       fTarget.machine:=aMachine;
+      fTarget.submachine:=GetDefaultSubMachineForMachine(fTarget.machine);
       exit;
     end;
   end;
@@ -250,6 +253,37 @@ begin
 
 end;
 
+procedure TParameters.ParseSubArchitecture(aList: TStringList; var index: integer; const parname: string);
+var tmp : string;
+    aSubMachineArm : TSubMachineTypeArm;
+    aSubMachineGeneric : TSubMachineTypeGeneric;
+begin
+  inc(index);
+  tmp:=DoMandatoryArgument(aList,index);
+  if tmp='' then
+    raise EArgumentMissingException.Create(parname);
+
+  case fTarget.machine of
+    mtarm,mtarmeb:
+      for aSubMachineArm:=low(TSubMachineTypeArm) to high(TSubMachineTypeArm) do
+        if SubMachinesArm[aSubMachineArm]=tmp then
+          begin
+            ftarget.submachine.subarm:=aSubMachineArm;
+            exit;
+          end;
+    else
+      for aSubMachineGeneric:=low(TSubMachineTypeGeneric) to high(TSubMachineTypeGeneric) do
+        if SubMachinesGen[aSubMachineGeneric]=tmp then
+          begin
+            ftarget.submachine.subgen:=aSubMachineGeneric;
+            exit;
+          end;
+  end;
+
+  raise EUnknownSubMachineException.Create(tmp);
+
+end;
+
 procedure TParameters.ParseConfigFile(aList: TStringList; var index: integer;
   const parname : string);
 var tmp : string;
@@ -333,6 +367,8 @@ begin
           ParseOutputFormat(fList,i,tmp)
         else if ((tmp='-a') or (tmp='--arch')) then
           ParseArchitecture(fList,i,tmp)
+        else if ((tmp='-s') or (tmp='--subarch')) then
+          ParseSubArchitecture(fList,i,tmp)
         else
           raise EUnknownParameterException.Create(tmp);
       end
@@ -356,6 +392,7 @@ begin
   fInputFiles:=TStringList.Create;
   fOutputFile:='';
   fTarget.machine:=mtnone;
+  GetDefaultSubMachineForMachine(fTarget.machine);
   fTarget.objformat:=ofnone;
 end;
 

+ 56 - 1
utils/fpcres/target.pas

@@ -25,6 +25,18 @@ type
                   mtsparc,mtalpha,mtia64,mtBigEndian,mtLittleEndian);
   TMachineTypes = set of TMachineType;
 
+  TSubMachineTypeArm = (smtarm_all,smtarm_v4t,smtarm_v6,smtarm_v5tej,smtarm_xscale,smtarm_v7);
+  TSubMachineTypeGeneric = (smtgen_all);
+
+  TSubMachineType = record
+    case TMachineType of
+      mtarm,mtarmeb:
+        (subarm: TSubMachineTypeArm);
+      mtnone, mti386,mtx86_64,mtppc,mtppc64,mtm68k,
+      mtsparc,mtalpha,mtia64,mtBigEndian,mtLittleEndian:
+        (subgen: TSubMachineTypeGeneric);
+  end;
+
   TObjFormat = (ofNone, ofRes, ofElf, ofCoff, ofMachO, ofExt);
   TObjFormats = set of TObjFormat;
   
@@ -42,10 +54,12 @@ type
 
   TResTarget = record
     machine : TMachineType;
+    submachine : TSubMachineType;
     objformat : TObjFormat;
   end;
 
 function GetDefaultMachineForFormat(aFormat : TObjFormat) : TMachineType;
+function GetDefaultSubMachineForMachine(aMachine: TMachineType) : TSubMachineType;
 function TargetToStr(const aTarget : TResTarget) : string;
 function MachineToStr(const aMachine : TMachineType) : string;
 function ObjFormatToStr(const aFormat : TObjFormat) : string;
@@ -67,6 +81,11 @@ var
     (name : 'bigendian';    formats : [ofExt]),                  //mtBigEndian
     (name : 'littleendian'; formats : [ofExt])                   //mtLittleEndian
   );
+
+  SubMachinesArm: array[TSubMachineTypeArm] of string[8] =
+    ('all','armv4','armv6','armv5tej','xscale','armv7');
+  SubMachinesGen: array[TSubMachineTypeGeneric] of string[3] =
+    ('all');
   
   ObjFormats : array[TObjFormat] of TFormatInfo =
   (
@@ -87,36 +106,47 @@ var
   (
   {$IFDEF CPUI386}
     machine : mti386;
+    submachine : (subgen: smtgen_all);
   {$ELSE}
   {$IFDEF CPUX86_64}
     machine : mtx86_64;
+    submachine : (subgen: smtgen_all);
   {$ELSE}
   {$IFDEF CPUPOWERPC32}
     machine : mtppc;
+    submachine : (subgen: smtgen_all);
   {$ELSE}
   {$IFDEF CPUPOWERPC64}
     machine : mtppc64;
+    submachine : (subgen: smtgen_all);
   {$ELSE}
   {$IFDEF CPUARM}
     {$IFDEF ENDIAN_LITTLE}
     machine : mtarm;
+    submachine : (subarm: smtarm_all);
     {$ELSE}
     machine : mtarmeb;
+    submachine : (subarm: smtarm_all);
     {$ENDIF}
   {$ELSE}
   {$IFDEF CPU68K}
     machine : mtm68k;
+    submachine : (subgen: smtgen_all);
   {$ELSE}
   {$IFDEF CPUSPARC}
     machine : mtsparc;
+    submachine : (subgen: smtgen_all);
   {$ELSE}
   {$IFDEF CPUALPHA}
     machine : mtalpha;
+    submachine : (subgen: smtgen_all);
   {$ELSE}
   {$IFDEF CPUIA64}
     machine : mtia64;
+    submachine : (subgen: smtgen_all);
   {$ELSE}
     machine : mti386;  //default i386
+    submachine : (subgen: smtgen_all);
   {$ENDIF}
   {$ENDIF}
   {$ENDIF}
@@ -162,18 +192,43 @@ begin
   Result:=Machines[aMachine].name;
 end;
 
+function SubMachineToStr(const aMachine : TMachineType; const aSubMachine : TSubMachineType) : string;
+begin
+  case aMachine of
+    mtarm,mtarmeb:
+      result:=SubMachinesArm[aSubMachine.subarm];
+    else
+      // no need to confuse people with the "all" suffix, it doesn't do
+      // anything anyway
+      result:='';
+  end;
+end;
+
 function ObjFormatToStr(const aFormat : TObjFormat) : string;
 begin
   Result:=ObjFormats[aFormat].name;
 end;
 
+function GetDefaultSubMachineForMachine(aMachine: TMachineType): TSubMachineType;
+begin
+  case aMachine of
+    mtarm,mtarmeb:
+      result.subarm:=smtarm_all;
+    else
+      result.subgen:=smtgen_all;
+  end;
+end;
+
 function TargetToStr(const aTarget : TResTarget) : string;
-var s1, s2 : string;
+var s1, s2, s3 : string;
 begin
   s1:=MachineToStr(aTarget.machine);
   s2:=ObjFormatToStr(aTarget.objformat);
+  s3:=SubMachineToStr(aTarget.Machine,aTarget.submachine);
   if (s1='') or (s2='') then Result:=s1+s2
   else Result:=s1+' - '+s2;
+  if s3<>'' then
+    Result:=Result+'-'+s3;
 end;
 
 end.