Browse Source

+ support for bitpacked arrays:
+ use {$bitpacking on/+} to change the meaning of "packed"
into "bitpacked" for arrays. This is the default for MacPas.
You can also define individual arrays as "bitpacked", but
this is not encouraged since this keyword is not known by
other compilers and therefore makes your code unportable.
+ pack(unpackedarray,index,packedarray) to pack
length(packedarray) elements starting at
unpackedarray[index] into packedarray.
+ unpack(packedarray,unpackedarray,index) to unpack
packedarray into unpackedarray, with the first
element being stored at unpackedarray[index]
* todo:
* "open packed arrays" and rtti for packed arrays are not
yet supported
* gdb does not properly support bitpacked arrays

git-svn-id: trunk@4449 -

Jonas Maebe 19 years ago
parent
commit
eccbc78e04

+ 2 - 0
compiler/compinnr.inc

@@ -66,6 +66,8 @@ const
    in_get_frame         = 56;
    in_get_caller_addr   = 57;
    in_get_caller_frame  = 58;
+   in_pack_x_y_z        = 59;
+   in_unpack_x_y_z      = 60;
 
 { Internal constant functions }
    in_const_sqr        = 100;

+ 26 - 0
compiler/cutils.pas

@@ -81,6 +81,7 @@ interface
        exponent value is returned in power.
     }
     function ispowerof2(value : int64;out power : longint) : boolean;
+    function nextpowerof2(value : int64; out power: longint) : int64;
     function backspace_quote(const s:string;const qchars:Tcharset):string;
     function octal_quote(const s:string;const qchars:Tcharset):string;
     function maybequoted(const s:string):string;
@@ -672,6 +673,31 @@ uses
       end;
 
 
+    function nextpowerof2(value : int64; out power: longint) : int64;
+    { 
+      returns the power of 2 >= value
+    }
+      var
+        i : longint;
+      begin
+        result := 0;
+        power := -1;
+        if ((value <= 0) or
+            (value >= $4000000000000000)) then
+          exit;
+        result := 1;
+        for i:=0 to 63 do
+          begin
+            if result>=value then
+              begin
+                power := i;
+                exit;
+              end;
+            result:=result shl 1;
+          end;
+      end;
+
+
     function backspace_quote(const s:string;const qchars:Tcharset):string;
 
     var i:byte;

+ 9 - 2
compiler/dbgdwarf.pas

@@ -887,21 +887,28 @@ implementation
       procedure append_dwarftag_arraydef(def:tarraydef);
         var
           size : aint;
+          elesize : aint;
         begin
           if is_special_array(def) then
             size:=def.elesize
           else
             size:=def.size;
+          
+          if not is_packed_array(def) then
+            elesize := def.elesize*8
+          else
+            elesize := def.elepackedbitsize;
+
           if assigned(def.typesym) then
             append_entry(DW_TAG_array_type,true,[
               DW_AT_name,DW_FORM_string,def.typesym.name+#0,
               DW_AT_byte_size,DW_FORM_udata,size,
-              DW_AT_stride_size,DW_FORM_udata,def.elesize*8
+              DW_AT_stride_size,DW_FORM_udata,elesize
               ])
           else
             append_entry(DW_TAG_array_type,true,[
               DW_AT_byte_size,DW_FORM_udata,size,
-              DW_AT_stride_size,DW_FORM_udata,def.elesize*8
+              DW_AT_stride_size,DW_FORM_udata,elesize
               ]);
           append_labelentry_ref(DW_AT_type,def_dwarf_lab(def.elementtype.def));
           if is_dynamic_array(def) then

+ 8 - 2
compiler/dbgstabs.pas

@@ -722,8 +722,14 @@ implementation
           formaldef :
             result:=def_stabstr_evaluate(def,'formal${numberstring};',[]);
           arraydef :
-            result:=def_stabstr_evaluate(def,'ar$1;$2;$3;$4',[def_stab_number(tarraydef(def).rangetype.def),
-               tostr(tarraydef(def).lowrange),tostr(tarraydef(def).highrange),def_stab_number(tarraydef(def).elementtype.def)]);
+            if not is_packed_array(def) then
+              result:=def_stabstr_evaluate(def,'ar$1;$2;$3;$4',[def_stab_number(tarraydef(def).rangetype.def),
+                 tostr(tarraydef(def).lowrange),tostr(tarraydef(def).highrange),def_stab_number(tarraydef(def).elementtype.def)])
+            else
+              // will only show highrange-lowrange+1 bits in gdb
+              result:=def_stabstr_evaluate(def,'@s$1;@S;S$2',[tostr(TConstExprInt(tarraydef(def).elepackedbitsize) * tarraydef(def).elecount),def_stabstr_evaluate(tarraydef(def).rangetype.def,'r${numberstring};$1;$2;',[tostr(tarraydef(def).lowrange),tostr(tarraydef(def).highrange)])]);
+// the @P seems to be ignored by gdb
+//              result:=def_stabstr_evaluate(def,'ar$1;$2;$3;$4;@P;',[def_stab_number(tarraydef(def).rangetype.def),tostr(tarraydef(def).lowrange),tostr(tarraydef(def).highrange),def_stab_number(tarraydef(def).elementtype.def)]);
           procdef :
             result:=procdef_stabstr(tprocdef(def));
           procvardef :

+ 9 - 1
compiler/defcmp.pas

@@ -601,8 +601,16 @@ implementation
                   case def_from.deftype of
                     arraydef :
                       begin
+                        { from/to packed array }
+                        if is_packed_array(def_from) xor
+                           is_packed_array(def_to) then
+                          { both must be packed }
+                          begin
+                            compare_defs_ext:=te_incompatible;
+                            exit;
+                          end
                         { to dynamic array }
-                        if is_dynamic_array(def_to) then
+                        else if is_dynamic_array(def_to) then
                          begin
                            if equal_defs(tarraydef(def_from).elementtype.def,tarraydef(def_to).elementtype.def) then
                              begin

+ 13 - 0
compiler/defutil.pas

@@ -123,6 +123,9 @@ interface
     }
     function is_special_array(p : tdef) : boolean;
 
+    {# Returns true if p is a bitpacked array }
+    function is_packed_array(p: tdef) : boolean;
+
     {# Returns true if p is a char array def }
     function is_chararray(p : tdef) : boolean;
 
@@ -568,6 +571,16 @@ implementation
                          (tstringdef(p).string_typ=st_shortstring);
       end;
 
+
+    { true if p is bit packed array def }
+    function is_packed_array(p: tdef) : boolean;
+      begin
+        is_packed_array :=
+           (p.deftype = arraydef) and
+           (ado_IsBitPacked in tarraydef(p).arrayoptions);
+      end;
+
+
     { true if p is a char array def }
     function is_chararray(p : tdef) : boolean;
       begin

+ 1 - 0
compiler/fpcdefs.inc

@@ -38,6 +38,7 @@
   {$define USECMOV}
   {$define SUPPORT_MMX}
   {$define cpumm}
+  {$define fewintregisters}
 {$endif i386}
 
 {$ifdef x86_64}

+ 1 - 1
compiler/globtype.pas

@@ -100,7 +100,7 @@ than 255 characters. That's why using Ansi Strings}
          { mmx }
          cs_mmx,cs_mmx_saturation,
          { parser }
-         cs_typed_addresses,cs_strict_var_strings,cs_ansistrings,
+         cs_typed_addresses,cs_strict_var_strings,cs_ansistrings,cs_bitpacking,
          { macpas specific}
          cs_external_var, cs_externally_visible
        );

+ 19 - 2
compiler/htypechk.pas

@@ -145,6 +145,7 @@ interface
     function  valid_for_formal_const(p : tnode; report_errors: boolean) : boolean;
     function  valid_for_var(p:tnode; report_errors: boolean):boolean;
     function  valid_for_assignment(p:tnode; report_errors: boolean):boolean;
+    function  valid_for_loopvar(p:tnode; report_errors: boolean):boolean;
     function  valid_for_addr(p : tnode; report_errors: boolean) : boolean;
 
     function allowenumop(nt:tnodetype):boolean;
@@ -165,7 +166,7 @@ implementation
        ;
 
     type
-      TValidAssign=(Valid_Property,Valid_Void,Valid_Const,Valid_Addr);
+      TValidAssign=(Valid_Property,Valid_Void,Valid_Const,Valid_Addr,Valid_Packed);
       TValidAssigns=set of TValidAssign;
 
 
@@ -1056,6 +1057,16 @@ implementation
                end;
              vecn :
                begin
+                 if { only check for first (= outermost) vec node }
+                    not gotvec and
+                    not(valid_packed in opts) and
+                    (tvecnode(hp).left.resulttype.def.deftype = arraydef) and
+                    (ado_IsBitPacked in tarraydef(tvecnode(hp).left.resulttype.def).arrayoptions) then
+                   begin
+                     if report_errors then
+                       CGMessagePos(hp.fileinfo,parser_e_packed_element_no_var_addr_loop);
+                     exit;
+                   end;
                  gotvec:=true;
                  { accesses to dyn. arrays override read only access in delphi }
                  if (m_delphi in aktmodeswitches) and is_dynamic_array(tunarynode(hp).left.resulttype.def) then
@@ -1310,7 +1321,13 @@ implementation
 
     function  valid_for_assignment(p:tnode; report_errors: boolean):boolean;
       begin
-        valid_for_assignment:=valid_for_assign(p,[valid_property],report_errors);
+        valid_for_assignment:=valid_for_assign(p,[valid_property,valid_packed],report_errors);
+      end;
+
+
+    function  valid_for_loopvar(p:tnode; report_errors: boolean):boolean;
+      begin
+        valid_for_loopvar:=valid_for_assign(p,[valid_property],report_errors);
       end;
 
 

+ 23 - 0
compiler/msg/errore.msg

@@ -1077,6 +1077,14 @@ parser_e_array_range_out_of_bounds=03220_E_The range of the array is too large
 % Regardless of the size taken up by its elements, an array cannot have more
 % than high(ptrint) elements. Additionally, the range type must be a subrange
 % of ptrint.
+parser_e_packed_element_no_var_addr_loop=03221_E_The address cannot be taken of bit packed array elements and record fields, nor can they be used as loop variables
+% If you declare an array or record as \var{packed} in Mac Pascal mode, it will
+% be packed at the bit level (currently only array bit packing is implemented though). This means it becomes impossible to take addresses
+% of individual array elements or records, even if their starting offset happens
+% to be aligned to a byte multiple. For performance reasons, they cannot be
+% used as loop variables either.
+parser_e_packed_dynamic_open_array=03222_E_Dynamic arrays cannot be packed
+% Only regular and open arrays can be packed
 % \end{description}
 #
 # Type Checking
@@ -1322,6 +1330,14 @@ type_w_double_c_varargs=04059_W_Converting constant real value to double for C v
 % this from happening, add an explicit typecast around the constant.
 type_e_class_or_cominterface_type_expected=04060_E_Class or COM interface type expected, but got "$1"
 % Some operators like the AS operator are only appliable to classes or COM interfaces.
+type_e_no_const_packed_array=04061_E_Constant packed arrays are not supported
+% You cannot declare a (bit)packed array as a typed constant.
+type_e_got_expected_packed_array=04062_E_Incompatible type for arg no. $1: Got "$2" expected "(Bit)Packed Array"
+% The compiler expects a (bit)packed array as the specified parameter
+type_e_got_expected_unpacked_array=04063_E_Incompatible type for arg no. $1: Got "$2" expected "(not packed) Array"
+% The compiler expects a regular (i.e., not packed) array as the specified parameter
+type_e_no_packed_inittable=04064_E_Elements of packed arrays cannot be of a type which need to be initialised
+% Support for packed arrays of types that need initialization (such as ansistrings, or records which contain ansistrings) is not yet implemented.
 % \end{description}
 #
 # Symtable
@@ -1827,6 +1843,13 @@ asmr_e_illegal_shifterop_syntax=07099_E_Syntax error while trying to parse a shi
 % asm
 %   orr     r2,r2,r2,lsl #8
 % end;
+asmr_e_packed_element=07100_E_Address of packed component is not at a byte boundary
+% Packed components (record fields and array elements) may start at an arbitrary
+% bit inside a byte. On CPU which do not support bit-addressable memory (which
+% includes all currently supported CPUs by FPC) you will therefore get an error
+% message when trying to index arrays with elements whose size is not a multiple
+% of 8 bits. The same goes for accessing record fields with such an address.
+% multiple of 8 bits.
 % \end{verbatim}
 #
 # Assembler/binary writers

+ 9 - 2
compiler/msgidx.inc

@@ -303,6 +303,8 @@ const
   parser_w_overridden_methods_not_same_ret=03218;
   parser_e_dispid_must_be_ord_const=03219;
   parser_e_array_range_out_of_bounds=03220;
+  parser_e_packed_element_no_var_addr_loop=03221;
+  parser_e_packed_dynamic_open_array=03222;
   type_e_mismatch=04000;
   type_e_incompatible_types=04001;
   type_e_not_equal_types=04002;
@@ -363,6 +365,10 @@ const
   type_e_illegal_count_var=04058;
   type_w_double_c_varargs=04059;
   type_e_class_or_cominterface_type_expected=04060;
+  type_e_no_const_packed_array=04061;
+  type_e_got_expected_packed_array=04062;
+  type_e_got_expected_unpacked_array=04063;
+  type_e_no_packed_inittable=04064;
   sym_e_id_not_found=05000;
   sym_f_internal_error_in_symtablestack=05001;
   sym_e_duplicate_id=05002;
@@ -530,6 +536,7 @@ const
   asmr_e_higher_cpu_mode_required=07097;
   asmr_w_unable_to_determine_reference_size_using_dword=07098;
   asmr_e_illegal_shifterop_syntax=07099;
+  asmr_e_packed_element=07100;
   asmw_f_too_many_asm_files=08000;
   asmw_f_assembler_output_not_supported=08001;
   asmw_f_comp_not_supported=08002;
@@ -686,9 +693,9 @@ const
   option_info=11024;
   option_help_pages=11025;
 
-  MsgTxtSize = 40392;
+  MsgTxtSize = 40910;
 
   MsgIdxMax : array[1..20] of longint=(
-    24,80,221,61,62,47,100,22,135,60,
+    24,80,223,65,62,47,101,22,135,60,
     41,1,1,1,1,1,1,1,1,1
   );

+ 204 - 193
compiler/msgtxt.inc

@@ -1,7 +1,7 @@
 {$ifdef Delphi}
-const msgtxt : array[0..000168] of string[240]=(
+const msgtxt : array[0..000170] of string[240]=(
 {$else Delphi}
-const msgtxt : array[0..000168,1..240] of char=(
+const msgtxt : array[0..000170,1..240] of char=(
 {$endif Delphi}
   '01019_bytes code'#000+
   '01020_bytes data'#000+
@@ -338,411 +338,422 @@ const msgtxt : array[0..000168,1..240] of char=(
   '"$1" which has another return type)'#000+
   '03219_E_Dispatch IDs must be ordinal constants'#000+
   '03220_E_The range of the array is too large'#000+
+  '03221_E_The address cannot be taken of bit packed array eleme','nts and'+
+  ' record fields, nor can they be used as loop variables'#000+
+  '03222_E_Dynamic arrays cannot be packed'#000+
   '04000_E_Type mismatch'#000+
-  '04001_E_Incompatible types: got "$1" ex','pected "$2"'#000+
+  '04001_E_Incompatible types: got "$1" expected "$2"'#000+
   '04002_E_Type mismatch between "$1" and "$2"'#000+
-  '04003_E_Type identifier expected'#000+
+  '04003_E_Type identifi','er expected'#000+
   '04004_E_Variable identifier expected'#000+
   '04005_E_Integer expression expected, but got "$1"'#000+
   '04006_E_Boolean expression expected, but got "$1"'#000+
-  '04007_E_Ordina','l expression expected'#000+
+  '04007_E_Ordinal expression expected'#000+
   '04008_E_pointer type expected, but got "$1"'#000+
-  '04009_E_class type expected, but got "$1"'#000+
+  '04009_E_cla','ss type expected, but got "$1"'#000+
   '04011_E_Can'#039't evaluate constant expression'#000+
   '04012_E_Set elements are not compatible'#000+
   '04013_E_Operation not implemented for sets'#000+
-  '04014_','W_Automatic type conversion from floating type to COMP which i'+
-  's an integer type'#000+
+  '04014_W_Automatic type conversion from floating type to COMP which is '+
+  'an integer ty','pe'#000+
   '04015_H_use DIV instead to get an integer result'#000+
   '04016_E_string types doesn'#039't match, because of $V+ mode'#000+
-  '04017_E_succ or pred on enums with assignments not poss','ible'#000+
+  '04017_E_succ or pred on enums with assignments not possible'#000+
   '04018_E_Can'#039't read or write variables of this type'#000+
-  '04019_E_Can'#039't use readln or writeln on typed file'#000+
+  '04019_E_Can'#039't use rea','dln or writeln on typed file'#000+
   '04020_E_Can'#039't use read or write on untyped file.'#000+
   '04021_E_Type conflict between set elements'#000+
-  '04022_W_lo/hi(dword/qword) returns the upp','er/lower word/dword'#000+
+  '04022_W_lo/hi(dword/qword) returns the upper/lower word/dword'#000+
   '04023_E_Integer or real expression expected'#000+
-  '04024_E_Wrong type "$1" in array constructor'#000+
+  '04024_E_Wrong',' type "$1" in array constructor'#000+
   '04025_E_Incompatible type for arg no. $1: Got "$2", expected "$3"'#000+
-  '04026_E_Method (variable) and Procedure (variable) are not compat','ibl'+
-  'e'#000+
+  '04026_E_Method (variable) and Procedure (variable) are not compatible'#000+
   '04027_E_Illegal constant passed to internal math function'#000+
-  '04028_E_Can'#039't get the address of constants'#000+
+  '04028_E_Can'#039't ','get the address of constants'#000+
   '04029_E_Argument can'#039't be assigned to'#000+
   '04030_E_Can'#039't assign local procedure/function to procedure variabl'+
   'e'#000+
-  '04031_E_Can'#039't assign values ','to an address'#000+
+  '04031_E_Can'#039't assign values to an address'#000+
   '04032_E_Can'#039't assign values to const variable'#000+
-  '04033_E_Array type required'#000+
+  '04033_E_Array typ','e required'#000+
   '04034_E_interface type expected, but got "$1"'#000+
   '04035_W_Mixing signed expressions and longwords gives a 64bit result'#000+
-  '04036_W_Mixing signed expressions and',' cardinals here may cause a ran'+
-  'ge check error'#000+
-  '04037_E_Typecast has different size ($1 -> $2) in assignment'#000+
+  '04036_W_Mixing signed expressions and cardinals here may cause a range'+
+  ' check error'#000+
+  '04037_E_Typecast has different ','size ($1 -> $2) in assignment'#000+
   '04038_E_enums with assignments can'#039't be used as array index'#000+
   '04039_E_Class or Object types "$1" and "$2" are not related'#000+
-  '04040_W_Class',' types "$1" and "$2" are not related'#000+
-  '04041_E_Class or interface type expected, but got "$1"'#000+
+  '04040_W_Class types "$1" and "$2" are not related'#000+
+  '04041_E_Class or interface type expected',', but got "$1"'#000+
   '04042_E_Type "$1" is not completely defined'#000+
   '04043_W_String literal has more characters than short string length'#000+
-  '04044_W_Comparison is always false d','ue to range of values'#000+
-  '04045_W_Comparison is always true due to range of values'#000+
+  '04044_W_Comparison is always false due to range of values'#000+
+  '04045_W_Comparison is always true due to range of value','s'#000+
   '04046_W_Constructing a class "$1" with abstract methods'#000+
   '04047_H_The left operand of the IN operator should be byte sized'#000+
-  '04048_W_Type size mismatch, possible los','s of data / range check erro'+
+  '04048_W_Type size mismatch, possible loss of data / range check error'#000+
+  '04049_H_Type size mismatch, possible loss of da','ta / range check erro'+
   'r'#000+
-  '04049_H_Type size mismatch, possible loss of data / range check error'#000+
   '04050_E_The address of an abstract method can'#039't be taken'#000+
   '04051_E_The operator is not applicable for the operand type'#000+
-  '04052_E_Constant Expres','sion expected'#000+
+  '04052_E_Constant Expression expected'#000+
   '04053_E_Operation "$1" not supported for types "$2" and "$3"'#000+
-  '04054_E_Illegal type conversion: "$1" to "$2"'#000+
+  '04','054_E_Illegal type conversion: "$1" to "$2"'#000+
   '04055_H_Conversion between ordinals and pointers is not portable'#000+
-  '04056_W_Conversion between ordinals and pointers is no','t portable'#000+
+  '04056_W_Conversion between ordinals and pointers is not portable'#000+
   '04057_E_Can'#039't determine which overloaded function to call'#000+
-  '04058_E_Illegal counter variable'#000+
+  '04058_E_','Illegal counter variable'#000+
   '04059_W_Converting constant real value to double for C variable argume'+
   'nt, add explicit typecast to prevent this.'#000+
-  '04060_E_Class or COM inte','rface type expected, but got "$1"'#000+
+  '04060_E_Class or COM interface type expected, but got "$1"'#000+
+  '04061_E_Constant packed arrays are not supp','orted'#000+
+  '04062_E_Incompatible type for arg no. $1: Got "$2" expected "(Bit)Pack'+
+  'ed Array"'#000+
+  '04063_E_Incompatible type for arg no. $1: Got "$2" expected "(not pack'+
+  'ed) Array"'#000+
+  '04064_E_Elements of packed arrays cannot be of a type which need to be'+
+  ' in','itialised'#000+
   '05000_E_Identifier not found "$1"'#000+
   '05001_F_Internal Error in SymTableStack()'#000+
   '05002_E_Duplicate identifier "$1"'#000+
   '05003_H_Identifier already defined in $1 at line $2'#000+
   '05004_E_Unknown identifier "$1"'#000+
-  '05005_E_Forw','ard declaration not solved "$1"'#000+
+  '05005_E_Forward declaration not solv','ed "$1"'#000+
   '05007_E_Error in type definition'#000+
   '05009_E_Forward type not resolved "$1"'#000+
   '05010_E_Only static variables can be used in static methods or outside'+
   ' methods'#000+
   '05012_F_record or class type expected'#000+
-  '05013_E_Instances o','f classes or objects with an abstract method are '+
+  '05013_E_Instances of classes or objects wit','h an abstract method are '+
   'not allowed'#000+
   '05014_W_Label not defined "$1"'#000+
   '05015_E_Label used but not defined "$1"'#000+
   '05016_E_Illegal label declaration'#000+
   '05017_E_GOTO and LABEL are not supported (use switch -Sg)'#000+
-  '05018_E_Label no','t found'#000+
-  '05019_E_identifier isn'#039't a label'#000+
+  '05018_E_Label not found'#000+
+  '05019_E_identifi','er isn'#039't a label'#000+
   '05020_E_label already defined'#000+
   '05021_E_illegal type declaration of set elements'#000+
   '05022_E_Forward class definition not resolved "$1"'#000+
   '05023_H_Unit "$1" not used in $2'#000+
   '05024_H_Parameter "$1" not used'#000+
-  '0502','5_N_Local variable "$1" not used'#000+
+  '05025_N_Local variable "$1" ','not used'#000+
   '05026_H_Value parameter "$1" is assigned but never used'#000+
   '05027_N_Local variable "$1" is assigned but never used'#000+
   '05028_H_Local $1 "$2" is not used'#000+
   '05029_N_Private field "$1.$2" is never used'#000+
-  '05030_N_Private fi','eld "$1.$2" is assigned but never used'#000+
+  '05030_N_Private field "$1.$2" is assigned ','but never used'#000+
   '05031_N_Private method "$1.$2" never used'#000+
   '05032_E_Set type expected'#000+
   '05033_W_Function result does not seem to be set'#000+
   '05034_W_Type "$1" is not aligned correctly in current record for C'#000+
-  '05035_E_Unknown re','cord field identifier "$1"'#000+
+  '05035_E_Unknown record field identifier "$','1"'#000+
   '05036_W_Local variable "$1" does not seem to be initialized'#000+
   '05037_W_Variable "$1" does not seem to be initialized'#000+
   '05038_E_identifier idents no member "$1"'#000+
   '05039_H_Found declaration: $1'#000+
-  '05040_E_Data element too lar','ge'#000+
-  '05042_E_No matching implementation for interface method "$1" found'#000+
+  '05040_E_Data element too large'#000+
+  '05042_E_No matching i','mplementation for interface method "$1" found'#000+
   '05043_W_Symbol "$1" is deprecated'#000+
   '05044_W_Symbol "$1" is not portable'#000+
   '05055_W_Symbol "$1" is not implemented'#000+
   '05056_E_Can'#039't create unique type from this type'#000+
-  '05057_H_Local',' variable "$1" does not seem to be initialized'#000+
+  '05057_H_Local variable "$1" does not ','seem to be initialized'#000+
   '05058_H_Variable "$1" does not seem to be initialized'#000+
   '05059_W_Function result variable does not seem to initialized'#000+
   '05060_H_Function result variable does not seem to be initialized'#000+
-  '05061_W_Vari','able "$1" read but nowhere assigned'#000+
+  '05061_W_Variable "$1" read but nowhe','re assigned'#000+
   '06009_E_Parameter list size exceeds 65535 bytes'#000+
   '06012_E_File types must be var parameters'#000+
   '06013_E_The use of a far pointer isn'#039't allowed there'#000+
   '06015_E_EXPORT declared functions can'#039't be called'#000+
-  '06016_W_Pos','sible illegal call of constructor or destructor'#000+
+  '06016_W_Possible illegal call of co','nstructor or destructor'#000+
   '06017_N_Inefficient code'#000+
   '06018_W_unreachable code'#000+
   '06020_E_Abstract methods can'#039't be called directly'#000+
   '06027_DL_Register $1 weight $2 $3'#000+
   '06029_DL_Stack frame is omitted'#000+
-  '06031_E_Object or class me','thods can'#039't be inline.'#000+
-  '06032_E_Procvar calls cannot be inline.'#000+
+  '06031_E_Object or class methods can'#039't be inline.'#000+
+  '0','6032_E_Procvar calls cannot be inline.'#000+
   '06033_E_No code for inline procedure stored'#000+
   '06035_E_Element zero of an ansi/wide- or longstring can'#039't be acces'+
   'sed, use (set)length instead'#000+
-  '06037_E_Constructors or destructors ca','n not be called inside a '#039'w'+
+  '06037_E_Constructors or destructors can not be called inside a',' '#039'w'+
   'ith'#039' clause'#000+
   '06038_E_Cannot call message handler methods directly'#000+
   '06039_E_Jump in or outside of an exception block'#000+
   '06040_E_Control flow statements aren'#039't allowed in a finally block'#000+
-  '06041_W_Parameters size exceeds l','imit for certain cpu'#039's'#000+
-  '06042_W_Local variable size exceed limit for certain cpu'#039's'#000+
+  '06041_W_Parameters size exceeds limit for certain cpu'#039's'#000+
+  '0','6042_W_Local variable size exceed limit for certain cpu'#039's'#000+
   '06043_E_Local variables size exceeds supported limit'#000+
   '06044_E_BREAK not allowed'#000+
   '06045_E_CONTINUE not allowed'#000+
-  '06046_F_Unknown compilerproc "$1". Check if you us','e the correct run '+
-  'time library.'#000+
+  '06046_F_Unknown compilerproc "$1". Check if you use the correct run ti'+
+  'me l','ibrary.'#000+
   '07000_DL_Starting $1 styled assembler parsing'#000+
   '07001_DL_Finished $1 styled assembler parsing'#000+
   '07002_E_Non-label pattern contains @'#000+
   '07004_E_Error building record offset'#000+
   '07005_E_OFFSET used without identifier'#000+
-  '070','06_E_TYPE used without identifier'#000+
+  '07006_E_TYPE used without i','dentifier'#000+
   '07007_E_Cannot use local variable or parameters here'#000+
   '07008_E_need to use OFFSET here'#000+
   '07009_E_need to use $ here'#000+
   '07010_E_Cannot use multiple relocatable symbols'#000+
   '07011_E_Relocatable symbol can only be added'#000+
-  '0','7012_E_Invalid constant expression'#000+
+  '07012_E_Invalid constant ','expression'#000+
   '07013_E_Relocatable symbol is not allowed'#000+
   '07014_E_Invalid reference syntax'#000+
   '07015_E_You can not reach $1 from that code'#000+
   '07016_E_Local symbols/labels aren'#039't allowed as references'#000+
-  '07017_E_Invalid base and ind','ex register usage'#000+
-  '07018_W_Possible error in object field handling'#000+
+  '07017_E_Invalid base and index register usage'#000+
+  '07018_','W_Possible error in object field handling'#000+
   '07019_E_Wrong scale factor specified'#000+
   '07020_E_Multiple index register usage'#000+
   '07021_E_Invalid operand type'#000+
   '07022_E_Invalid string as opcode operand: $1'#000+
-  '07023_W_@CODE and @DATA n','ot supported'#000+
-  '07024_E_Null label references are not allowed'#000+
+  '07023_W_@CODE and @DATA not supported'#000+
+  '07024_E_Nul','l label references are not allowed'#000+
   '07025_E_Divide by zero in asm evaluator'#000+
   '07026_E_Illegal expression'#000+
   '07027_E_escape sequence ignored: $1'#000+
   '07028_E_Invalid symbol reference'#000+
-  '07029_W_Fwait can cause emulation problems wi','th emu387'#000+
-  '07030_W_$1 without operand translated into $1P'#000+
+  '07029_W_Fwait can cause emulation problems with emu387'#000+
+  '07030_W_$1 wit','hout operand translated into $1P'#000+
   '07031_W_ENTER instruction is not supported by Linux kernel'#000+
   '07032_W_Calling an overload function in assembler'#000+
   '07033_E_Unsupported symbol type for operand'#000+
-  '07034_E_Constant value out of ','bounds'#000+
-  '07035_E_Error converting decimal $1'#000+
+  '07034_E_Constant value out of bounds'#000+
+  '07035_E_Error con','verting decimal $1'#000+
   '07036_E_Error converting octal $1'#000+
   '07037_E_Error converting binary $1'#000+
   '07038_E_Error converting hexadecimal $1'#000+
   '07039_H_$1 translated to $2'#000+
   '07040_W_$1 is associated to an overloaded function'#000+
-  '07041_E_C','annot use SELF outside a method'#000+
+  '07041_E_Cannot use SELF outside a',' method'#000+
   '07042_E_Cannot use OLDEBP outside a nested procedure'#000+
   '07043_W_Procedures can'#039't return any value in asm code'#000+
   '07044_E_SEG not supported'#000+
   '07045_E_Size suffix and destination or source size do not match'#000+
-  '07046_W_Siz','e suffix and destination or source size do not match'#000+
+  '07046_W_Size suffix and destination',' or source size do not match'#000+
   '07047_E_Assembler syntax error'#000+
   '07048_E_Invalid combination of opcode and operands'#000+
   '07049_E_Assembler syntax error in operand'#000+
   '07050_E_Assembler syntax error in constant'#000+
-  '07051_E_Invalid Stri','ng expression'#000+
-  '07052_W_constant with symbol $1 for address which is not on a pointer'#000+
+  '07051_E_Invalid String expression'#000+
+  '07052_W_co','nstant with symbol $1 for address which is not on a pointe'+
+  'r'#000+
   '07053_E_Unrecognized opcode $1'#000+
   '07054_E_Invalid or missing opcode'#000+
   '07055_E_Invalid combination of prefix and opcode: $1'#000+
-  '07056_E_Invalid combination of overrid','e and opcode: $1'#000+
-  '07057_E_Too many operands on line'#000+
+  '07056_E_Invalid combination of override and opcode: $1'#000+
+  '07057_E','_Too many operands on line'#000+
   '07058_W_NEAR ignored'#000+
   '07059_W_FAR ignored'#000+
   '07060_E_Duplicate local symbol $1'#000+
   '07061_E_Undefined local symbol $1'#000+
   '07062_E_Unknown label identifier $1'#000+
   '07063_E_Invalid register name'#000+
-  '07064_E_Invali','d floating point register name'#000+
+  '07064_E_Invalid floating point registe','r name'#000+
   '07066_W_Modulo not supported'#000+
   '07067_E_Invalid floating point constant $1'#000+
   '07068_E_Invalid floating point expression'#000+
   '07069_E_Wrong symbol type'#000+
   '07070_E_Cannot index a local var or parameter with a register'#000+
-  '07071_E','_Invalid segment override expression'#000+
+  '07071_E_Invalid segment overrid','e expression'#000+
   '07072_W_Identifier $1 supposed external'#000+
   '07073_E_Strings not allowed as constants'#000+
   '07074_No type of variable specified'#000+
   '07075_E_assembler code not returned to text section'#000+
-  '07076_E_Not a directive or local s','ymbol $1'#000+
-  '07077_E_Using a defined name as a local label'#000+
+  '07076_E_Not a directive or local symbol $1'#000+
+  '07077_E_Using a',' defined name as a local label'#000+
   '07078_E_Dollar token is used without an identifier'#000+
   '07079_W_32bit constant created for address'#000+
   '07080_N_.align is target specific, use .balign or .p2align'#000+
-  '07081_E_Can'#039't access fields dire','ctly for parameters'#000+
-  '07082_E_Can'#039't access fields of objects/classes directly'#000+
+  '07081_E_Can'#039't access fields directly for parameters'#000+
+  '0708','2_E_Can'#039't access fields of objects/classes directly'#000+
   '07083_E_No size specified and unable to determine the size of the oper'+
   'ands'#000+
   '07084_E_Cannot use RESULT in this function'#000+
-  '07086_W_"$1" without operand translated into "','$1 %st,%st(1)"'#000+
-  '07087_W_"$1 %st(n)" translated into "$1 %st,%st(n)"'#000+
+  '07086_W_"$1" without operand translated into "$1 %st,%st(1)"'#000+
+  '07087_W_"','$1 %st(n)" translated into "$1 %st,%st(n)"'#000+
   '07088_W_"$1 %st(n)" translated into "$1 %st(n),%st"'#000+
   '07089_E_Char < not allowed here'#000+
   '07090_E_Char > not allowed here'#000+
   '07093_W_ALIGN not supported'#000+
-  '07094_E_Inc and Dec cannot be',' together'#000+
-  '07095_E_Invalid reglist for movem'#000+
+  '07094_E_Inc and Dec cannot be together'#000+
+  '07095_E_Invali','d reglist for movem'#000+
   '07096_E_Reglist invalid for opcode'#000+
   '07097_E_Higher cpu mode required ($1)'#000+
   '07098_W_No size specified and unable to determine the size of the oper'+
   'ands, using DWORD as default'#000+
-  '07099_E_Syntax error whi','le trying to parse a shifter operand'#000+
+  '07099_E_Syntax error while trying to parse a shi','fter operand'#000+
+  '07100_E_Address of packed component is not at a byte boundary'#000+
   '08000_F_Too many assembler files'#000+
   '08001_F_Selected assembler output not supported'#000+
   '08002_F_Comp not supported'#000+
   '08003_F_Direct not support for binary writers'#000+
-  '08004_E_Allocating of data is only allowed in bss',' section'#000+
+  '08004_E_All','ocating of data is only allowed in bss section'#000+
   '08005_F_No binary writer selected'#000+
   '08006_E_Asm: Opcode $1 not in table'#000+
   '08007_E_Asm: $1 invalid combination of opcode and operands'#000+
   '08008_E_Asm: 16 Bit references not supported'#000+
-  '08009_E_Asm: Invalid effective address'#000+
-  '08010_E_Asm: Immed','iate or reference expected'#000+
+  '08009_E_Asm: Invali','d effective address'#000+
+  '08010_E_Asm: Immediate or reference expected'#000+
   '08011_E_Asm: $1 value exceeds bounds $2'#000+
   '08012_E_Asm: Short jump is out of range $1'#000+
   '08013_E_Asm: Undefined label $1'#000+
   '08014_E_Asm: Comp type not supported for this target'#000+
-  '08015_E_Asm: Extended type not supported for ','this target'#000+
+  '08015_E','_Asm: Extended type not supported for this target'#000+
   '08016_E_Asm: Duplicate label $1'#000+
   '08017_E_Asm: Redefined label $1'#000+
   '08018_E_Asm: First defined here'#000+
   '08019_E_Asm: Invalid register $1'#000+
   '08020_E_Asm: 16 or 32 Bit references not supported'#000+
-  '08021_E_Asm: 64 Bit operands not supported'#000+
-  '09000','_W_Source operating system redefined'#000+
+  '08021_E_As','m: 64 Bit operands not supported'#000+
+  '09000_W_Source operating system redefined'#000+
   '09001_I_Assembling (pipe) $1'#000+
   '09002_E_Can'#039't create assembler file: $1'#000+
   '09003_E_Can'#039't create object file: $1'#000+
   '09004_E_Can'#039't create archive file: $1'#000+
-  '09005_E_Assembler $1 not found, switching to external assem','bling'#000+
+  '09005_E_Assembler $1 ','not found, switching to external assembling'#000+
   '09006_T_Using assembler: $1'#000+
   '09007_E_Error while assembling exitcode $1'#000+
   '09008_E_Can'#039't call the assembler, error $1 switching to external a'+
   'ssembling'#000+
   '09009_I_Assembling $1'#000+
-  '09010_I_Assembling with smartlinking $1'#000+
-  '09011_W_Object $1 not fou','nd, Linking may fail !'#000+
+  '09010_I_Assembling with sma','rtlinking $1'#000+
+  '09011_W_Object $1 not found, Linking may fail !'#000+
   '09012_W_Library $1 not found, Linking may fail !'#000+
   '09013_E_Error while linking'#000+
   '09014_E_Can'#039't call the linker, switching to external linking'#000+
   '09015_I_Linking $1'#000+
-  '09016_E_Util $1 not found, switching to external linking'#000+
-  '090','17_T_Using util $1'#000+
+  '09016_E_Util $1 not fo','und, switching to external linking'#000+
+  '09017_T_Using util $1'#000+
   '09018_E_Creation of Executables not supported'#000+
   '09019_E_Creation of Dynamic/Shared Libraries not supported'#000+
   '09020_I_Closing script $1'#000+
-  '09021_E_resource compiler not found, switching to external mode'#000+
-  '09022_I_Compiling resource',' $1'#000+
+  '09021_E_resource compiler not found, switching to ex','ternal mode'#000+
+  '09022_I_Compiling resource $1'#000+
   '09023_T_unit $1 can'#039't be statically linked, switching to smart lin'+
   'king'#000+
   '09024_T_unit $1 can'#039't be smart linked, switching to static linking'+
   #000+
-  '09025_T_unit $1 can'#039't be shared linked, switching to static linkin'+
-  'g'#000+
-  '09026_E_unit $1 can'#039't be smart',' or static linked'#000+
+  '09025_T_unit $1 can'#039't be shared linked, switching to static ','link'+
+  'ing'#000+
+  '09026_E_unit $1 can'#039't be smart or static linked'#000+
   '09027_E_unit $1 can'#039't be shared or static linked'#000+
   '09028_D_Calling resource compiler "$1" with "$2" as command line'#000+
   '09128_F_Can'#039't post process executable $1'#000+
-  '09129_F_Can'#039't open executable $1'#000+
+  '09129_F_Can'#039't open executable',' $1'#000+
   '09130_X_Size of Code: $1 bytes'#000+
-  '091','31_X_Size of initialized data: $1 bytes'#000+
+  '09131_X_Size of initialized data: $1 bytes'#000+
   '09132_X_Size of uninitialized data: $1 bytes'#000+
   '09133_X_Stack space reserved: $1 bytes'#000+
   '09134_X_Stack space committed: $1 bytes'#000+
   '10000_T_Unitsearch: $1'#000+
-  '10001_T_PPU Loading $1'#000+
+  '10001_T_PPU Loa','ding $1'#000+
   '10002_U_PPU Name: $1'#000+
-  '10003_U_P','PU Flags: $1'#000+
+  '10003_U_PPU Flags: $1'#000+
   '10004_U_PPU Crc: $1'#000+
   '10005_U_PPU Time: $1'#000+
   '10006_U_PPU File too short'#000+
   '10007_U_PPU Invalid Header (no PPU at the begin)'#000+
   '10008_U_PPU Invalid Version $1'#000+
-  '10009_U_PPU is compiled for another processor'#000+
-  '10010_U_PPU is compiled for an ot','her target'#000+
+  '10009_U_PPU is compiled for another proce','ssor'#000+
+  '10010_U_PPU is compiled for an other target'#000+
   '10011_U_PPU Source: $1'#000+
   '10012_U_Writing $1'#000+
   '10013_F_Can'#039't Write PPU-File'#000+
   '10014_F_Error reading PPU-File'#000+
   '10015_F_unexpected end of PPU-File'#000+
   '10016_F_Invalid PPU-File entry: $1'#000+
-  '10017_F_PPU Dbx count problem'#000+
-  '10018_E_Illegal unit name: ','$1'#000+
+  '10017_F_PPU Dbx cou','nt problem'#000+
+  '10018_E_Illegal unit name: $1'#000+
   '10019_F_Too much units'#000+
   '10020_F_Circular unit reference between $1 and $2'#000+
   '10021_F_Can'#039't compile unit $1, no sources available'#000+
   '10022_F_Can'#039't find unit $1'#000+
   '10023_W_Unit $1 was not found but $2 exists'#000+
-  '10024_F_Unit $1 searched but $2 found'#000+
-  '100','25_W_Compiling the system unit requires the -Us switch'#000+
+  '100','24_F_Unit $1 searched but $2 found'#000+
+  '10025_W_Compiling the system unit requires the -Us switch'#000+
   '10026_F_There were $1 errors compiling module, stopping'#000+
   '10027_U_Load from $1 ($2) unit $3'#000+
   '10028_U_Recompiling $1, checksum changed for $2'#000+
-  '10029_U_Recompiling $1, source found only'#000+
-  '10030','_U_Recompiling unit, static lib is older than ppufile'#000+
+  '10029_U_R','ecompiling $1, source found only'#000+
+  '10030_U_Recompiling unit, static lib is older than ppufile'#000+
   '10031_U_Recompiling unit, shared lib is older than ppufile'#000+
   '10032_U_Recompiling unit, obj and asm are older than ppufile'#000+
-  '10033_U_Recompiling unit, obj is older than asm'#000+
-  '10034_U_Parsing in','terface of $1'#000+
+  '10033_U_Recompiling unit, ob','j is older than asm'#000+
+  '10034_U_Parsing interface of $1'#000+
   '10035_U_Parsing implementation of $1'#000+
   '10036_U_Second load for unit $1'#000+
   '10037_U_PPU Check file $1 time $2'#000+
   '10040_W_Can'#039't recompile unit $1, but found modifed include files'#000+
-  '10041_H_File $1 is newer than Release PPU file $2'#000+
-  '10042_U_','Using a unit which was not compiled with correct FPU mode'#000+
+  '10041_H_File $1 is n','ewer than Release PPU file $2'#000+
+  '10042_U_Using a unit which was not compiled with correct FPU mode'#000+
   '10043_U_Loading interface units from $1'#000+
   '10044_U_Loading implementation units from $1'#000+
   '10045_U_Interface CRC changed for unit $1'#000+
-  '10046_U_Implementation CRC changed for unit $1'#000+
-  '10047_U_','Finished compiling unit $1'#000+
+  '10046_U_Implement','ation CRC changed for unit $1'#000+
+  '10047_U_Finished compiling unit $1'#000+
   '10048_U_Add dependency of $1 to $2'#000+
   '10049_U_No reload, is caller: $1'#000+
   '10050_U_No reload, already in second compile: $1'#000+
   '10051_U_Flag for reload: $1'#000+
   '10052_U_Forced reloading'#000+
-  '10053_U_Previous state of $1: $2'#000+
-  '10054_U_Al','ready compiling $1, setting second compile'#000+
+  '10053','_U_Previous state of $1: $2'#000+
+  '10054_U_Already compiling $1, setting second compile'#000+
   '10055_U_Loading unit $1'#000+
   '10056_U_Finished loading unit $1'#000+
   '10057_U_Registering new unit $1'#000+
   '10058_U_Re-resolving unit $1'#000+
-  '10059_U_Skipping re-resolving unit $1, still loading used units'#000+
-  '11000_O_$1 [opt','ions] <inputfile> [options]'#000+
+  '10059_U_Skipping re-resolving unit $1, st','ill loading used units'#000+
+  '11000_O_$1 [options] <inputfile> [options]'#000+
   '11001_W_Only one source file supported'#000+
   '11002_W_DEF file can be created only for OS/2'#000+
   '11003_E_nested response files are not supported'#000+
-  '11004_F_No source file name in command line'#000+
-  '11005_N_No option inside $1 config ','file'#000+
+  '11004_F_No source file name in command li','ne'#000+
+  '11005_N_No option inside $1 config file'#000+
   '11006_E_Illegal parameter: $1'#000+
   '11007_H_-? writes help pages'#000+
   '11008_F_Too many config files nested'#000+
   '11009_F_Unable to open file $1'#000+
   '11010_D_Reading further options from $1'#000+
-  '11011_W_Target is already set to: $1'#000+
-  '11012_W_Shared libs not support','ed on DOS platform, reverting to stat'+
-  'ic'#000+
+  '11011_W_Target is already set ','to: $1'#000+
+  '11012_W_Shared libs not supported on DOS platform, reverting to static'+
+  #000+
   '11013_F_too many IF(N)DEFs'#000+
   '11014_F_too many ENDIFs'#000+
   '11015_F_open conditional at the end of the file'#000+
-  '11016_W_Debug information generation is not supported by this executab'+
-  'le'#000+
-  '11017_H_Try recompiling with',' -dGDB'#000+
+  '11016_W_Debug information generation is not supported by this e','xecut'+
+  'able'#000+
+  '11017_H_Try recompiling with -dGDB'#000+
   '11018_W_You are using the obsolete switch $1'#000+
   '11019_W_You are using the obsolete switch $1, please use $2'#000+
   '11020_N_Switching assembler to default source writing assembler'#000+
-  '11021_W_Assembler output selected "$1" is not compatible with "$','2"'#000+
+  '11021_W_Assembler output s','elected "$1" is not compatible with "$2"'#000+
   '11022_W_"$1" assembler use forced'#000+
   '11026_T_Reading options from file $1'#000+
   '11027_T_Reading options from environment $1'#000+
   '11028_D_Handling option "$1"'#000+
   '11029__*** press enter ***'#000+
-  '11030_H_Start of reading config file $1'#000+
-  '11031_H_End of reading con','fig file $1'#000+
+  '11030_H_Start of reading con','fig file $1'#000+
+  '11031_H_End of reading config file $1'#000+
   '11032_D_interpreting option "$1"'#000+
   '11036_D_interpreting firstpass option "$1"'#000+
   '11033_D_interpreting file option "$1"'#000+
   '11034_D_Reading config file "$1"'#000+
   '11035_D_found source file name "$1"'#000+
-  '11039_E_Unknown code page'#000+
-  '11040_F_Config file',' $1 is a directory'#000+
+  '11039_E','_Unknown code page'#000+
+  '11040_F_Config file $1 is a directory'#000+
   '11023_Free Pascal Compiler version $FPCFULLVERSION [$FPCDATE] for $FPC'+
   'CPU'#010+
   'Copyright (c) 1993-2006 by Florian Klaempfl'#000+
   '11024_Free Pascal Compiler version $FPCVERSION'#010+
   #010+
-  'Compiler Date      : $FPCDATE'#010+
-  'Compiler CPU Target: $FPC','CPU'#010+
+  'Compiler Date    ','  : $FPCDATE'#010+
+  'Compiler CPU Target: $FPCCPU'#010+
   #010+
   'Supported targets:'#010+
   '  $OSTARGETS'#010+
@@ -756,91 +767,91 @@ const msgtxt : array[0..000168,1..240] of char=(
   'Supported Optimizations:'#010+
   '  $OPTIMIZATIONS'#010+
   #010+
-  'This program comes under the GNU General Public Lice','nce'#010+
+  'This program c','omes under the GNU General Public Licence'#010+
   'For more information read COPYING.FPC'#010+
   #010+
   'Report bugs,suggestions etc to:'#010+
   '                 [email protected]'#000+
   '11025_**0*_put + after a boolean switch option to enable it, - to disa'+
   'ble it'#010+
-  '**1a_the compiler doesn'#039't delete the generated asse','mbler file'#010+
+  '**1a_the comp','iler doesn'#039't delete the generated assembler file'#010+
   '**2al_list sourcecode lines in assembler file'#010+
   '**2an_list node info in assembler file'#010+
   '*L2ap_use pipes instead of creating temporary assembler files'#010+
-  '**2ar_list register allocation/release info in assembler file'#010+
-  '**2at_list temp allo','cation/release info in assembler file'#010+
+  '**2ar_list register allocation/release info ','in assembler file'#010+
+  '**2at_list temp allocation/release info in assembler file'#010+
   '**1A<x>_output format:'#010+
   '**2Adefault_use default assembler'#010+
   '3*2Aas_assemble using GNU AS'#010+
   '3*2Anasmcoff_coff (Go32v2) file using Nasm'#010+
-  '3*2Anasmelf_elf32 (Linux) file using Nasm'#010+
-  '3*2Anasmwin32_Win32 object file',' using Nasm'#010+
+  '3*2Anasmelf_elf32 (Linux) file usin','g Nasm'#010+
+  '3*2Anasmwin32_Win32 object file using Nasm'#010+
   '3*2Anasmwdosx_Win32/WDOSX object file using Nasm'#010+
   '3*2Awasm_obj file using Wasm (Watcom)'#010+
   '3*2Anasmobj_obj file using Nasm'#010+
   '3*2Amasm_obj file using Masm (Microsoft)'#010+
-  '3*2Atasm_obj file using Tasm (Borland)'#010+
-  '3*2Aelf_elf32 (Linux) using i','nternal writer'#010+
+  '3*2Atasm_obj file using Tasm (','Borland)'#010+
+  '3*2Aelf_elf32 (Linux) using internal writer'#010+
   '3*2Acoff_coff (Go32v2) using internal writer'#010+
   '3*2Apecoff_pecoff (Win32) using internal writer'#010+
   '4*2Aas_assemble using GNU AS'#010+
   '6*2Aas_Unix o-file using GNU AS'#010+
   '6*2Agas_GNU Motorola assembler'#010+
-  '6*2Amit_MIT Syntax (old GAS)'#010+
-  '6*2Amot_Sta','ndard Motorola assembler'#010+
+  '6*','2Amit_MIT Syntax (old GAS)'#010+
+  '6*2Amot_Standard Motorola assembler'#010+
   'A*2Aas_assemble using GNU AS'#010+
   'P*2Aas_assemble using GNU AS'#010+
   'S*2Aas_assemble using GNU AS'#010+
   '**1b_generate browser info'#010+
   '**2bl_generate local symbol info'#010+
   '**1B_build all modules'#010+
-  '**1C<x>_code generation options:'#010+
-  '**2Cc<x>_set',' default calling convention to <x>'#010+
+  '**1C<x>','_code generation options:'#010+
+  '**2Cc<x>_set default calling convention to <x>'#010+
   '**2CD_create also dynamic library (not supported)'#010+
   '**2Ce_Compilation with emulated floating point opcodes'#010+
-  '**2Cf<x>_Select fpu instruction set to use, see fpc -i for possible va'+
-  'lues'#010+
+  '**2Cf<x>_Select fpu instruction set to use, see fpc -i for pos','sible '+
+  'values'#010+
   '**2Cg_Generate PIC code'#010+
-  '*','*2Ch<n>_<n> bytes heap (between 1023 and 67107840)'#010+
+  '**2Ch<n>_<n> bytes heap (between 1023 and 67107840)'#010+
   '**2Ci_IO-checking'#010+
   '**2Cn_omit linking stage'#010+
   '**2Co_check overflow of integer operations'#010+
   '**2Cp<x>_select instruction set, see fpc -i for possible values'#010+
-  '**2Cr_range checking'#010+
-  '**2CR_verify objec','t method call validity'#010+
+  '*','*2Cr_range checking'#010+
+  '**2CR_verify object method call validity'#010+
   '**2Cs<n>_set stack size to <n>'#010+
   '**2Ct_stack checking'#010+
   '**2CX_create also smartlinked library'#010+
   '**1d<x>_defines the symbol <x>'#010+
   '**1D_generate a DEF file'#010+
   '**2Dd<x>_set description to <x>'#010+
-  '**2Dv<x>_set DLL version to <x>'#010+
-  '*O2Dw_P','M application'#010+
+  '*','*2Dv<x>_set DLL version to <x>'#010+
+  '*O2Dw_PM application'#010+
   '**1e<x>_set path to executable'#010+
   '**1E_same as -Cn'#010+
   '**1F<x>_set file names and paths:'#010+
   '**2Fa<x>[,y]_for a program load first units <x> and [y] before uses is'+
   ' parsed'#010+
-  '**2Fc<x>_sets input codepage to <x>'#010+
-  '**2FD<x>_sets the directory wh','ere to search for compiler utilities'#010+
+  '**2Fc<x>_sets input codepage',' to <x>'#010+
+  '**2FD<x>_sets the directory where to search for compiler utilities'#010+
   '**2Fe<x>_redirect error output to <x>'#010+
   '**2FE<x>_set exe/unit output path to <x>'#010+
   '**2Fi<x>_adds <x> to include path'#010+
   '**2Fl<x>_adds <x> to library path'#010+
-  '**2FL<x>_uses <x> as dynamic linker'#010+
-  '**2Fo<x>_adds <x> to',' object path'#010+
+  '**2FL<x>_uses <x> ','as dynamic linker'#010+
+  '**2Fo<x>_adds <x> to object path'#010+
   '**2Fr<x>_load error message file <x>'#010+
   '**2Fu<x>_adds <x> to unit path'#010+
   '**2FU<x>_set unit output path to <x>, overrides -FE'#010+
   '*g1g_generate debugger information:'#010+
-  '*g2gc_generate checks for pointers'#010+
+  '*g2gc_generate checks for pointer','s'#010+
   '*g2gd_use dbx'#010+
   '*g2gg_use gsym'#010+
-  '*g2gh_u','se heap trace unit (for memory leak debugging)'#010+
+  '*g2gh_use heap trace unit (for memory leak debugging)'#010+
   '*g2gl_use line info unit to show more info for backtraces'#010+
   '*g2gt_trash local variables (to detect uninitialized uses)'#010+
-  '*g2gv_generates programs traceable with valgrind'#010+
-  '*g2gw_generate dwarf debugg','ing info'#010+
+  '*g2gv_generates programs traceable wit','h valgrind'#010+
+  '*g2gw_generate dwarf debugging info'#010+
   '**1i_information'#010+
   '**2iD_return compiler date'#010+
   '**2iV_return compiler version'#010+
@@ -848,81 +859,81 @@ const msgtxt : array[0..000168,1..240] of char=(
   '**2iSO_return compiler OS'#010+
   '**2iSP_return compiler processor'#010+
   '**2iTO_return target OS'#010+
-  '**2iTP_return target processor'#010+
-  '**1I<x>_','adds <x> to include path'#010+
+  '*','*2iTP_return target processor'#010+
+  '**1I<x>_adds <x> to include path'#010+
   '**1k<x>_Pass <x> to the linker'#010+
   '**1l_write logo'#010+
   '**1M<x>_set language mode to <x>'#010+
   '**2Mfpc_free pascal dialect (default)'#010+
   '**2Mobjfpc_switch some Delphi 2 extensions on'#010+
-  '**2Mdelphi_tries to be Delphi compatible'#010+
-  '**2Mtp_tri','es to be TP/BP 7.0 compatible'#010+
+  '**2Mdelphi_tr','ies to be Delphi compatible'#010+
+  '**2Mtp_tries to be TP/BP 7.0 compatible'#010+
   '**2Mgpc_tries to be gpc compatible'#010+
   '**2Mmacpas_tries to be compatible to the macintosh pascal dialects'#010+
   '**1n_don'#039't read the default config file'#010+
-  '**1N<x>_node tree optimizations'#010+
+  '**1N<x>_node tree optimization','s'#010+
   '**2Nu_unroll loops'#010+
-  '**1o<x>_change th','e name of the executable produced to <x>'#010+
+  '**1o<x>_change the name of the executable produced to <x>'#010+
   '**1O<x>_optimizations:'#010+
   '**2O-_disable optimizations'#010+
   '**2O1_level 1 optimizations (quick and debugger friendly)'#010+
-  '**2O2_level 2 optimizations (-O1 + quick optimizations)'#010+
-  '**2O3_level 3 optimizations (-O2 +',' slow optimizations)'#010+
+  '**2O2_level 2 optimizations (-O1 + quick optimizatio','ns)'#010+
+  '**2O3_level 3 optimizations (-O2 + slow optimizations)'#010+
   '**2Oa<x>=<y>_set alignment'#010+
   '**2Oo[NO]<x>_enable or disable optimizations, see fpc -i for possible '+
   'values'#010+
   '**2Op<x>_set target cpu for optimizing, see fpc -i for possible values'+
   #010+
-  '**2Os_generate smaller code'#010+
-  '**1pg_generate p','rofile code for gprof (defines FPC_PROFILE)'#010+
+  '**2Os_','generate smaller code'#010+
+  '**1pg_generate profile code for gprof (defines FPC_PROFILE)'#010+
   '**1R<x>_assembler reading style:'#010+
   '**2Rdefault_use default assembler'#010+
   '3*2Ratt_read AT&T style assembler'#010+
   '3*2Rintel_read Intel style assembler'#010+
-  '6*2RMOT_read motorola style assembler'#010+
-  '**1S<x>_syntax optio','ns:'#010+
+  '6*2RMOT_read motorol','a style assembler'#010+
+  '**1S<x>_syntax options:'#010+
   '**2S2_same as -Mobjfpc'#010+
   '**2Sc_supports operators like C (*=,+=,/= and -=)'#010+
   '**2Sa_include assertion code.'#010+
   '**2Sd_same as -Mdelphi'#010+
   '**2Se<x>_error options. <x> is a combination of the following:'#010+
-  '**3*_<n> : compiler stops after the <n> errors ','(default is 1)'#010+
+  '**3*_<n> ',': compiler stops after the <n> errors (default is 1)'#010+
   '**3*_w : compiler stops also after warnings'#010+
   '**3*_n : compiler stops also after notes'#010+
   '**3*_h : compiler stops also after hints'#010+
   '**2Sg_allow LABEL and GOTO'#010+
   '**2Sh_Use ansistrings'#010+
-  '**2Si_support C++ styled INLINE'#010+
-  '**2Sk_load fpcylix',' unit'#010+
+  '**2Si_suppor','t C++ styled INLINE'#010+
+  '**2Sk_load fpcylix unit'#010+
   '**2SI<x>_set interface style to <x>'#010+
   '**3SIcom_COM compatible interface (default)'#010+
   '**3SIcorba_CORBA compatible interface'#010+
   '**2Sm_support macros like C (global)'#010+
   '**2So_same as -Mtp'#010+
   '**2Sp_same as -Mgpc'#010+
-  '**2Ss_constructor name must be init (des','tructor must be done)'#010+
+  '**','2Ss_constructor name must be init (destructor must be done)'#010+
   '**2St_allow static keyword in objects'#010+
   '**1s_don'#039't call assembler and linker'#010+
   '**2sh_Generate script to link on host'#010+
   '**2st_Generate script to link on target'#010+
-  '**2sr_Skip register allocation phase (use with -alr)'#010+
-  '**1T<x>_Targ','et operating system:'#010+
+  '**2sr_Skip register allocat','ion phase (use with -alr)'#010+
+  '**1T<x>_Target operating system:'#010+
   '3*2Temx_OS/2 via EMX (including EMX/RSX extender)'#010+
   '3*2Tfreebsd_FreeBSD'#010+
   '3*2Tgo32v2_Version 2 of DJ Delorie DOS extender'#010+
   '3*2Tlinux_Linux'#010+
   '3*2Tnetbsd_NetBSD'#010+
-  '3*2Tnetware_Novell Netware Module (clib)'#010+
-  '3*2Tnetwlibc_Novell Netwar','e Module (libc)'#010+
+  '3*2Tnetware_Novell Netware Mo','dule (clib)'#010+
+  '3*2Tnetwlibc_Novell Netware Module (libc)'#010+
   '3*2Topenbsd_OpenBSD'#010+
   '3*2Tos2_OS/2 / eComStation'#010+
   '3*2Tsunos_SunOS/Solaris'#010+
   '3*2Twatcom_Watcom compatible DOS extender'#010+
   '3*2Twdosx_WDOSX DOS extender'#010+
   '3*2Twin32_Windows 32 Bit'#010+
-  '3*2Twince_Windows CE'#010+
+  '3*2Twince_Windows C','E'#010+
   '4*2Tlinux_Linux'#010+
-  '6*2Tamiga_Commodore ','Amiga'#010+
+  '6*2Tamiga_Commodore Amiga'#010+
   '6*2Tatari_Atari ST/STe/TT'#010+
   '6*2Tlinux_Linux/m68k'#010+
   '6*2Tmacos_Macintosh m68k (not supported)'#010+
@@ -930,8 +941,8 @@ const msgtxt : array[0..000168,1..240] of char=(
   'A*2Tlinux_Linux'#010+
   'A*2Twince_Windows CE'#010+
   'P*2Tamiga_AmigaOS on PowerPC'#010+
-  'P*2Tdarwin_Darwin and MacOS X on PowerPC'#010+
-  'P*2Tlinux_Linux on Po','werPC'#010+
+  'P*2Tdarwin_Darwin and Ma','cOS X on PowerPC'#010+
+  'P*2Tlinux_Linux on PowerPC'#010+
   'P*2Tmacos_MacOS (classic) on PowerPC'#010+
   'P*2Tmorphos_MorphOS'#010+
   'S*2Tlinux_Linux'#010+
@@ -939,48 +950,48 @@ const msgtxt : array[0..000168,1..240] of char=(
   '**1U_unit options:'#010+
   '**2Un_don'#039't check the unit name'#010+
   '**2Ur_generate release unit files'#010+
-  '**2Us_compile a system unit'#010+
-  '**1v<x>_Be verb','ose. <x> is a combination of the following letters:'#010+
+  '**2Us','_compile a system unit'#010+
+  '**1v<x>_Be verbose. <x> is a combination of the following letters:'#010+
   '**2*_e : Show errors (default)       0 : Show nothing (except errors)'#010+
   '**2*_w : Show warnings               u : Show unit info'#010+
-  '**2*_n : Show notes                  t : Show tried/used files',#010+
+  '**2*_n : Show notes     ','             t : Show tried/used files'#010+
   '**2*_h : Show hints                  c : Show conditionals'#010+
   '**2*_i : Show general info           d : Show debug info'#010+
   '**2*_l : Show linenumbers            r : Rhide/GCC compatibility mode'#010+
-  '**2*_a : Show everything             x : Executable i','nfo (Win32 only'+
+  '**2*_a : Show e','verything             x : Executable info (Win32 only'+
   ')'#010+
   '**2*_b : Write file names messages with full path'#010+
   '**2*_v : write fpcdebug.txt with     p : Write tree.log with parse tre'+
   'e'#010+
   '**2*_    lots of debugging info'#010+
-  '3*1W<x>_Win32-like target options'#010+
+  '3*1W<x>_Win32-like target optio','ns'#010+
   '3*2WB_Create a relocatable image'#010+
-  '3*','2WB<x>_Set Image base to Hexadecimal <x> value'#010+
+  '3*2WB<x>_Set Image base to Hexadecimal <x> value'#010+
   '3*2WC_Specify console type application'#010+
   '3*2WD_Use DEFFILE to export functions of DLL or EXE'#010+
   '3*2WF_Specify full-screen type application (OS/2 only)'#010+
-  '3*2WG_Specify graphic type application'#010+
-  '3*2WN_Do',' not generate relocation code (necessary for debugging)'#010+
+  '3*2WG_Spe','cify graphic type application'#010+
+  '3*2WN_Do not generate relocation code (necessary for debugging)'#010+
   '3*2WR_Generate relocation code'#010+
   'P*2WC_Specify console type application (MacOS only)'#010+
   'P*2WG_Specify graphic type application (MacOS only)'#010+
-  'P*2WT_Specify tool type application (MPW tool, Ma','cOS only)'#010+
+  'P*2WT_Speci','fy tool type application (MPW tool, MacOS only)'#010+
   '**1X_executable options:'#010+
   '**2Xc_pass --shared to the linker (Unix only)'#010+
   '**2Xd_don'#039't use standard library search path (needed for cross com'+
   'pile)'#010+
   '**2Xe_use external linker'#010+
-  '**2XD_try to link units dynamic          (defines FPC_LINK_DY','NAMIC)'#010+
+  '**2XD_try to link units',' dynamic          (defines FPC_LINK_DYNAMIC)'#010+
   '**2Xi_use internal linker'#010+
   '**2Xm_generate link map'#010+
   '**2XM<x>_set the name of the '#039'main'#039' program routine (default i'+
   's '#039'main'#039')'#010+
   '**2XP<x>_prepend the binutils names with the prefix <x>'#010+
-  '**2Xr<x>_set library search path to <x> (needed for cro','ss compile)'#010+
+  '**2Xr<x>_set libr','ary search path to <x> (needed for cross compile)'#010+
   '**2Xs_strip all symbols from executable'#010+
   '**2XS_try to link units static (default) (defines FPC_LINK_STATIC)'#010+
   '**2Xt_link with static libraries (-static is passed to linker)'#010+
-  '**2XX_try to link units smart            (defines FPC_LINK','_SMART)'#010+
+  '**2XX_try to link un','its smart            (defines FPC_LINK_SMART)'#010+
   '**1*_'#010+
   '**1?_shows this help'#010+
   '**1h_shows this help without waiting'#000

+ 1 - 1
compiler/ncgcal.pas

@@ -126,7 +126,7 @@ implementation
           exit;
 
         { Move flags and jump in register to make it less complex }
-        if left.location.loc in [LOC_FLAGS,LOC_JUMP,LOC_SUBSETREG,LOC_CSUBSETREG] then
+        if left.location.loc in [LOC_FLAGS,LOC_JUMP,LOC_SUBSETREG,LOC_CSUBSETREG,LOC_SUBSETREF,LOC_CSUBSETREF] then
           location_force_reg(current_asmdata.CurrAsmList,left.location,def_cgsize(left.resulttype.def),false);
 
         { Handle Floating point types differently }

+ 11 - 0
compiler/ncgld.pas

@@ -614,6 +614,9 @@ implementation
                     LOC_SUBSETREG,
                     LOC_CSUBSETREG:
                       cg.a_load_ref_subsetreg(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.reference,left.location.sreg);
+                    LOC_SUBSETREF,
+                    LOC_CSUBSETREF:
+                      cg.a_load_ref_subsetref(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.reference,left.location.sref);
                     else
                       internalerror(200203284);
                   end;
@@ -686,6 +689,12 @@ implementation
                   cg.a_load_subsetreg_loc(current_asmdata.CurrAsmList,
                       right.location.size,right.location.sreg,left.location);
                 end;
+              LOC_SUBSETREF,
+              LOC_CSUBSETREF:
+                begin
+                  cg.a_load_subsetref_loc(current_asmdata.CurrAsmList,
+                      right.location.size,right.location.sref,left.location);
+                end;
               LOC_JUMP :
                 begin
                   current_asmdata.getjumplabel(hlabel);
@@ -760,6 +769,8 @@ implementation
         tmpreg  : tregister;
         paraloc : tcgparalocation;
       begin
+        if is_packed_array(resulttype.def) then
+          internalerror(200608042);
         dovariant:=(nf_forcevaria in flags) or is_variant_array(resulttype.def);
         if dovariant then
           elesize:=sizeof(aint)+sizeof(aint)

+ 84 - 11
compiler/ncgmem.pas

@@ -67,6 +67,7 @@ interface
            so it points to the correct address.
          }
          procedure update_reference_reg_mul(reg:tregister;l:aint);virtual;
+         procedure update_reference_reg_packed(reg:tregister;l:aint);virtual;
          procedure second_wideansistring;virtual;
          procedure second_dynamicarray;virtual;
        public
@@ -387,7 +388,10 @@ implementation
          else
           begin
             if (left.resulttype.def.deftype=arraydef) then
-             get_mul_size:=tarraydef(left.resulttype.def).elesize
+             if not is_packed_array(left.resulttype.def) then
+              get_mul_size:=tarraydef(left.resulttype.def).elesize
+             else
+              get_mul_size:=tarraydef(left.resulttype.def).elepackedbitsize
             else
              get_mul_size:=resulttype.def.size;
           end
@@ -423,6 +427,47 @@ implementation
        end;
 
 
+     procedure tcgvecnode.update_reference_reg_packed(reg:tregister;l:aint);
+       var
+         sref: tsubsetreference;
+         offsetreg: tregister;
+         byteoffs, bitoffs, alignpower: aint;
+       begin
+         if (l mod 8) = 0 then
+           begin
+             update_reference_reg_mul(reg,l div 8);
+             exit;
+           end;
+         if (l > 8*sizeof(aint)) then
+           internalerror(200608051);
+         sref.ref := location.reference;
+         offsetreg := cg.getaddressregister(current_asmdata.CurrAsmList);
+         cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SUB,OS_INT,tarraydef(left.resulttype.def).lowrange,reg);
+         cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_IMUL,OS_INT,l,reg);
+         { keep alignment for index }
+         sref.ref.alignment := left.resulttype.def.alignment;
+         if not ispowerof2(sref.ref.alignment,alignpower) then
+           internalerror(2006081201);
+         cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHR,OS_ADDR,3+alignpower,reg,offsetreg);
+         cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SHL,OS_ADDR,alignpower,offsetreg);
+         if (sref.ref.base = NR_NO) then
+           sref.ref.base := offsetreg
+         else if (sref.ref.index = NR_NO) then
+           sref.ref.index := offsetreg
+         else
+           begin
+             cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_ADD,OS_ADDR,sref.ref.base,offsetreg);
+             sref.ref.base := offsetreg;
+           end;
+         cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_AND,OS_INT,(1 shl (3+alignpower))-1,reg);
+         sref.bitindexreg := reg;
+         sref.startbit := 0;
+         sref.bitlen := resulttype.def.packedbitsize;
+         location.loc := LOC_SUBSETREF;
+         location.sref := sref;
+       end;
+
+
      procedure tcgvecnode.second_wideansistring;
        begin
        end;
@@ -505,14 +550,21 @@ implementation
          href     : treference;
          otl,ofl  : tasmlabel;
          newsize  : tcgsize;
-         mulsize  : aint;
+         mulsize,
+         bytemulsize,
+         alignpow : aint;
          isjump   : boolean;
          paraloc1,
          paraloc2 : tcgpara;
+         subsetref : tsubsetreference;
       begin
          paraloc1.init;
          paraloc2.init;
-         mulsize := get_mul_size;
+         mulsize:=get_mul_size;
+         if not is_packed_array(left.resulttype.def) then
+           bytemulsize:=mulsize
+         else
+           bytemulsize:=mulsize div 8;
 
          newsize:=def_cgsize(resulttype.def);
          secondpass(left);
@@ -589,8 +641,10 @@ implementation
 
          { offset can only differ from 0 if arraydef }
          if (left.resulttype.def.deftype=arraydef) and
-            not(is_dynamic_array(left.resulttype.def)) then
-           dec(location.reference.offset,mulsize*tarraydef(left.resulttype.def).lowrange);
+            not(is_dynamic_array(left.resulttype.def)) and
+            (not(is_packed_array(left.resulttype.def)) or
+             (mulsize mod 8 = 0)) then
+           dec(location.reference.offset,bytemulsize*tarraydef(left.resulttype.def).lowrange);
 
          if right.nodetype=ordconstn then
            begin
@@ -659,18 +713,34 @@ implementation
                      end;
                    end;
               end;
-              inc(location.reference.offset,
-                  mulsize*tordconstnode(right).value);
+              if not(is_packed_array(left.resulttype.def)) or
+                 (mulsize mod 8 = 0) then
+                inc(location.reference.offset,
+                  bytemulsize*tordconstnode(right).value)
+              else
+                begin
+                  subsetref.ref := location.reference;
+                  subsetref.ref.alignment := left.resulttype.def.alignment;
+                  if not ispowerof2(subsetref.ref.alignment,alignpow) then
+                    internalerror(2006081212);
+                  inc(subsetref.ref.offset,((mulsize * (tordconstnode(right).value-tarraydef(left.resulttype.def).lowrange)) shr (3+alignpow)) shl alignpow);
+                  subsetref.bitindexreg := NR_NO;
+                  subsetref.startbit := (mulsize * (tordconstnode(right).value-tarraydef(left.resulttype.def).lowrange)) and ((1 shl (3+alignpow))-1);
+                  subsetref.bitlen := resulttype.def.packedbitsize;
+                  location.loc := LOC_SUBSETREF;
+                  location.sref := subsetref;
+                end;
            end
          else
          { not nodetype=ordconstn }
            begin
-              if (cs_opt_regvar in aktoptimizerswitches) and
+              if (cs_opt_level1 in aktoptimizerswitches) and
                  { if we do range checking, we don't }
                  { need that fancy code (it would be }
                  { buggy)                            }
                  not(cs_check_range in aktlocalswitches) and
-                 (left.resulttype.def.deftype=arraydef) then
+                 (left.resulttype.def.deftype=arraydef) and
+                 not is_packed_array(left.resulttype.def) then
                 begin
                    extraoffset:=0;
                    if (right.nodetype=addn) then
@@ -737,7 +807,7 @@ implementation
               secondpass(right);
 
               { if mulsize = 1, we won't have to modify the index }
-              location_force_reg(current_asmdata.CurrAsmList,right.location,OS_ADDR,(mulsize = 1));
+              location_force_reg(current_asmdata.CurrAsmList,right.location,OS_ADDR,not is_packed_array(left.resulttype.def) and (mulsize = 1) );
 
               if isjump then
                begin
@@ -797,7 +867,10 @@ implementation
 
               { insert the register and the multiplication factor in the
                 reference }
-              update_reference_reg_mul(right.location.register,mulsize);
+              if not is_packed_array(left.resulttype.def) then
+                update_reference_reg_mul(right.location.register,mulsize)
+              else
+                update_reference_reg_packed(right.location.register,mulsize);
            end;
 
         location.size:=newsize;

+ 20 - 10
compiler/ncgutil.pas

@@ -290,10 +290,11 @@ implementation
                 begin
                    opsize:=def_cgsize(p.resulttype.def);
                    case p.location.loc of
-                     LOC_SUBSETREG,LOC_CSUBSETREG:
+                     LOC_SUBSETREG,LOC_CSUBSETREG,
+                     LOC_SUBSETREF,LOC_CSUBSETREF:
                        begin
                          tmpreg := cg.getintregister(list,OS_INT);
-                         cg.a_load_subsetreg_reg(list,p.location.size,OS_INT,p.location.sreg,tmpreg);
+                         cg.a_load_loc_reg(list,OS_INT,p.location,tmpreg);
                          cg.a_cmp_const_reg_label(list,OS_INT,OC_NE,0,tmpreg,current_procinfo.CurrTrueLabel);
                          cg.a_jmp_always(list,current_procinfo.CurrFalseLabel);
                        end;
@@ -582,15 +583,17 @@ implementation
                        (l.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
                       inc(l.reference.offset,TCGSize2Size[l.size]-TCGSize2Size[dst_size]);
 {$ifdef x86}
-                  if not (l.loc in [LOC_SUBSETREG,LOC_CSUBSETREG]) then
+                  if not (l.loc in [LOC_SUBSETREG,LOC_CSUBSETREG,LOC_SUBSETREF,LOC_CSUBSETREF]) then
                      l.size:=dst_size;
 {$endif x86}
                   end;
                  cg.a_load_loc_reg(list,dst_size,l,hregister);
-{$ifndef x86}
-                 if (TCGSize2Size[dst_size]<TCGSize2Size[l.size]) then
-                   l.size:=dst_size;
-{$endif not x86}
+                 if (TCGSize2Size[dst_size]<TCGSize2Size[l.size])
+{$ifdef x86}
+                    and (l.loc in [LOC_SUBSETREG,LOC_CSUBSETREG,LOC_SUBSETREF,LOC_CSUBSETREF])
+{$endif x86}
+                   then
+                     l.size:=dst_size;
                end;
            end;
            if not const_location then
@@ -755,10 +758,12 @@ implementation
               l.reference:=r;
             end;
           LOC_SUBSETREG,
-          LOC_CSUBSETREG:
+          LOC_CSUBSETREG,
+          LOC_SUBSETREF,
+          LOC_CSUBSETREF:
             begin
               tg.GetTemp(list,TCGSize2Size[l.size],tt_normal,r);
-              cg.a_load_subsetreg_ref(list,l.size,l.size,l.sreg,r);
+              cg.a_load_loc_ref(list,l.size,l,r);
               location_reset(l,LOC_REFERENCE,l.size);
               l.reference:=r;
             end;
@@ -848,7 +853,11 @@ implementation
                   if not assigned(hsym) then
                     internalerror(200306061);
                   hreg:=cg.getaddressregister(list);
-                  cg.g_copyvaluepara_openarray(list,href,hsym.localloc,tarraydef(tparavarsym(p).vartype.def).elesize,hreg);
+                  if not is_packed_array(tparavarsym(p).vartype.def) then
+                    cg.g_copyvaluepara_openarray(list,href,hsym.localloc,tarraydef(tparavarsym(p).vartype.def).elesize,hreg)
+                  else
+                    internalerror(2006080401);
+//                    cg.g_copyvaluepara_packedopenarray(list,href,hsym.localloc,tarraydef(tparavarsym(p).vartype.def).elepackedbitsize,hreg);
                   cg.a_load_reg_loc(list,OS_ADDR,hreg,tparavarsym(p).localloc);
                 end;
             end
@@ -2775,3 +2784,4 @@ implementation
       end;
 
 end.
+

+ 208 - 7
compiler/ninl.pas

@@ -40,6 +40,10 @@ interface
           function pass_1 : tnode;override;
           function det_resulttype:tnode;override;
           function docompare(p: tnode): boolean; override;
+
+          { pack and unpack are changed into for-loops by the compiler }
+          function first_pack_unpack: tnode; virtual;
+
           { All the following routines currently
             call compilerprocs, unless they are
             overriden in which case, the code
@@ -1227,6 +1231,79 @@ implementation
         end;
 
 
+      procedure handle_pack_unpack;
+        var
+          source, target, index: tcallparanode;
+          unpackedarraydef, packedarraydef: tarraydef;
+          tempindex: TConstExprInt;
+        begin
+          resulttype:=voidtype;
+          
+          unpackedarraydef := nil;
+          packedarraydef := nil;
+          source := tcallparanode(left);
+          if (inlinenumber = in_unpack_x_y_z) then
+            begin
+              target := tcallparanode(source.right);
+              index := tcallparanode(target.right);
+
+              { source must be a packed array }
+              if not is_packed_array(source.left.resulttype.def) then
+                CGMessagePos2(source.left.fileinfo,type_e_got_expected_packed_array,'1',source.left.resulttype.def.gettypename)
+              else
+                packedarraydef := tarraydef(source.left.resulttype.def);
+              { target can be any kind of array, as long as it's not packed }
+              if (target.left.resulttype.def.deftype <> arraydef) or
+                 is_packed_array(target.left.resulttype.def) then
+                CGMessagePos2(target.left.fileinfo,type_e_got_expected_unpacked_array,'2',target.left.resulttype.def.gettypename)
+              else
+                unpackedarraydef := tarraydef(target.left.resulttype.def);
+            end
+          else
+            begin
+              index := tcallparanode(source.right);
+              target := tcallparanode(index.right);
+
+              { source can be any kind of array, as long as it's not packed }
+              if (source.left.resulttype.def.deftype <> arraydef) or
+                 is_packed_array(source.left.resulttype.def) then
+                CGMessagePos2(source.left.fileinfo,type_e_got_expected_unpacked_array,'1',source.left.resulttype.def.gettypename)
+              else
+                unpackedarraydef := tarraydef(source.left.resulttype.def);
+              { target must be a packed array }
+              if not is_packed_array(target.left.resulttype.def) then
+                CGMessagePos2(target.left.fileinfo,type_e_got_expected_packed_array,'3',target.left.resulttype.def.gettypename)
+              else
+                packedarraydef := tarraydef(target.left.resulttype.def);
+            end;
+
+          if assigned(unpackedarraydef) then
+            begin
+              { index must be compatible with the unpacked array's indextype }
+              inserttypeconv(index.left,unpackedarraydef.rangetype);
+              
+              { range check at compile time if possible }
+              if assigned(packedarraydef) and
+                 (index.left.nodetype = ordconstn) and
+                 not is_special_array(unpackedarraydef) then
+                begin
+                  testrange(unpackedarraydef,tordconstnode(index.left).value,false);
+                  tempindex := tordconstnode(index.left).value + packedarraydef.highrange-packedarraydef.lowrange;
+                  testrange(unpackedarraydef,tempindex,false);
+                end;
+            end;
+
+          { source array is read and must be valid }
+          set_varstate(source.left,vs_read,[vsf_must_be_valid]);
+          { target array is written }
+          valid_for_assignment(target.left,true);
+          set_varstate(target.left,vs_written,[]);
+          { index in the unpacked array is read and must be valid }
+          set_varstate(index.left,vs_read,[vsf_must_be_valid]);
+        end;
+      
+
+
       var
          vl,vl2    : TConstExprInt;
          vr        : bestreal;
@@ -1360,10 +1437,32 @@ implementation
                       begin
                         hp:=caddnode.create(addn,hightree,
                                          cordconstnode.create(1,sinttype,false));
-                        if (left.resulttype.def.deftype=arraydef) and
-                           (tarraydef(left.resulttype.def).elesize<>1) then
-                          hp:=caddnode.create(muln,hp,cordconstnode.create(tarraydef(
-                            left.resulttype.def).elesize,sinttype,true));
+                        if (left.resulttype.def.deftype=arraydef) then
+                          if not is_packed_array(tarraydef(left.resulttype.def)) then
+                            begin
+                              if (tarraydef(left.resulttype.def).elesize<>1) then
+                                hp:=caddnode.create(muln,hp,cordconstnode.create(tarraydef(
+                                  left.resulttype.def).elesize,sinttype,true));
+                            end
+                          else if (tarraydef(left.resulttype.def).elepackedbitsize <> 8) then
+                            begin
+                              { no packed open array support yet }
+                              if (hp.nodetype <> ordconstn) then
+                                internalerror(2006081511);
+                              hp.free;
+                              hp := cordconstnode.create(left.resulttype.def.size,sinttype,true);
+{
+                              hp:=
+                                 ctypeconvnode.create_explicit(sinttype,
+                                   cmoddivnode.create(divn,
+                                     caddnode.create(addn,
+                                       caddnode.create(muln,hp,cordconstnode.create(tarraydef(
+                                         left.resulttype.def).elepackedbitsize,s64inttype,true)),
+                                       cordconstnode.create(a,s64inttype,true)),
+                                     cordconstnode.create(8,s64inttype,true)),
+                                   sinttype);
+}
+                            end;
                         result:=hp;
                       end;
                    end
@@ -1724,7 +1823,7 @@ implementation
               in_exclude_x_y:
                 begin
                   resulttype:=voidtype;
-                  { the parser already checks whether we have two (and exectly two) }
+                  { the parser already checks whether we have two (and exactly two) }
                   { parameters (JM)                                                 }
                   { first param must be var }
                   valid_for_var(tcallparanode(left).left,true);
@@ -1741,6 +1840,11 @@ implementation
                   else
                     CGMessage(type_e_mismatch);
                 end;
+              in_pack_x_y_z,
+              in_unpack_x_y_z :
+                begin
+                  handle_pack_unpack;
+                end;
 
               in_slice_x:
                 begin
@@ -1810,10 +1914,10 @@ implementation
                         else
                          begin
                            if is_open_string(left.resulttype.def) then
-			     begin
+                            begin
                                set_varstate(left,vs_read,[]);
                                result:=load_high_value_node(tparavarsym(tloadnode(left).symtableentry))
-			     end
+                            end
                            else
                              result:=cordconstnode.create(tstringdef(left.resulttype.def).len,u8inttype,true);
                          end;
@@ -2301,6 +2405,12 @@ implementation
 {$endif SUPPORT_MMX}
            end;
 
+         in_pack_x_y_z,
+         in_unpack_x_y_z:
+           begin
+             result:=first_pack_unpack;
+           end;
+
          in_exp_real:
            begin
              result:= first_exp_real;
@@ -2566,6 +2676,97 @@ implementation
         left := nil;
       end;
 
+     function tinlinenode.first_pack_unpack: tnode;
+       var
+         loopstatement    : tstatementnode;
+         loop             : tblocknode;
+         loopvar          : ttempcreatenode;
+         tempnode,
+         source,
+         target,
+         index,
+         unpackednode,
+         packednode,
+         sourcevecindex,
+         targetvecindex,
+         loopbody         : tnode;
+         temprangetype    : ttype;
+         ulorange,
+         uhirange,
+         plorange,
+         phirange          : TConstExprInt;
+       begin
+         { transform into a for loop which assigns the data of the (un)packed }
+         { array to the other one                                             }
+         source := left;
+         if (inlinenumber = in_unpack_x_y_z) then
+           begin
+             target := tcallparanode(source).right;
+             index := tcallparanode(target).right;
+             packednode := tcallparanode(source).left;
+             unpackednode := tcallparanode(target).left;
+           end
+         else
+           begin
+             index := tcallparanode(source).right;
+             target := tcallparanode(index).right;
+             packednode := tcallparanode(target).left;
+             unpackednode := tcallparanode(source).left;
+           end;
+         source := tcallparanode(source).left;
+         target := tcallparanode(target).left;
+         index := tcallparanode(index).left;
+
+         loop := internalstatements(loopstatement);
+         loopvar := ctempcreatenode.create(
+           tarraydef(packednode.resulttype.def).rangetype,
+           tarraydef(packednode.resulttype.def).rangetype.def.size,
+           tt_persistent,true);
+         addstatement(loopstatement,loopvar);
+
+         { For range checking: we have to convert to an integer type (in case the index type }
+         { is an enum), add the index and loop variable together, convert the result         }
+         { implicitly to an orddef with range equal to the rangetype to get range checking   }
+         { and finally convert it explicitly back to the actual rangetype to avoid type      }
+         { errors                                                                            }
+         temprangetype.reset;
+         getrange(unpackednode.resulttype.def,ulorange,uhirange);
+         getrange(packednode.resulttype.def,plorange,phirange);
+         temprangetype.setdef(torddef.create(torddef(sinttype.def).typ,ulorange,uhirange));
+         sourcevecindex := ctemprefnode.create(loopvar);
+         targetvecindex := ctypeconvnode.create_internal(index.getcopy,sinttype);
+         targetvecindex := caddnode.create(subn,targetvecindex,cordconstnode.create(plorange,sinttype,true));
+         targetvecindex := caddnode.create(addn,targetvecindex,ctemprefnode.create(loopvar));
+         targetvecindex := ctypeconvnode.create(targetvecindex,temprangetype);
+         targetvecindex := ctypeconvnode.create_explicit(targetvecindex,tarraydef(unpackednode.resulttype.def).rangetype);
+
+         if (inlinenumber = in_pack_x_y_z) then
+           begin
+             { swap source and target vec indices }
+             tempnode := sourcevecindex;
+             sourcevecindex := targetvecindex;
+             targetvecindex := tempnode;
+           end;
+
+         { create the assignment in the loop body }
+         loopbody :=
+           cassignmentnode.create(
+             cvecnode.create(target.getcopy,targetvecindex),
+             cvecnode.create(source.getcopy,sourcevecindex)
+           );
+         { create the actual for loop }
+         tempnode := cfornode.create(
+           ctemprefnode.create(loopvar),
+           cinlinenode.create(in_low_x,false,packednode.getcopy),
+           cinlinenode.create(in_high_x,false,packednode.getcopy),
+           loopbody,
+           false);
+         addstatement(loopstatement,tempnode);
+         { free the loop counter }
+         addstatement(loopstatement,ctempdeletenode.create(loopvar));
+         result := loop;
+       end;
+
 begin
    cinlinenode:=tinlinenode;
 end.

+ 14 - 0
compiler/pexpr.pas

@@ -812,6 +812,20 @@ implementation
               consume(_RKLAMMER);
             end;
 
+          in_pack_x_y_z,
+          in_unpack_x_y_z :
+            begin
+              consume(_LKLAMMER);
+              in_args:=true;
+              p1:=comp_expr(true);
+              consume(_COMMA);
+              p2:=comp_expr(true);
+              consume(_COMMA);
+              paras:=comp_expr(true);
+              statement_syssym:=geninlinenode(l,false,ccallparanode.create(p1,ccallparanode.create(p2,ccallparanode.create(paras,nil))));
+              consume(_RKLAMMER);
+            end;
+
           in_assert_x_y :
             begin
               consume(_LKLAMMER);

+ 1 - 1
compiler/ppu.pas

@@ -43,7 +43,7 @@ type
 {$endif Test_Double_checksum}
 
 const
-  CurrentPPUVersion=59;
+  CurrentPPUVersion=60;
 
 { buffer sizes }
   maxentrysize = 1024;

+ 1 - 1
compiler/pstatmnt.pas

@@ -309,7 +309,7 @@ implementation
          consume(_FOR);
 
          hloopvar:=factor(false);
-         valid_for_assignment(hloopvar,true);
+         valid_for_loopvar(hloopvar,true);
 
          { Check loop variable }
          loopvarsym:=nil;

+ 2 - 0
compiler/psystem.pas

@@ -71,6 +71,8 @@ implementation
         systemunit.insert(tsyssym.create('Succ',in_succ_x));
         systemunit.insert(tsyssym.create('Exclude',in_exclude_x_y));
         systemunit.insert(tsyssym.create('Include',in_include_x_y));
+        systemunit.insert(tsyssym.create('Pack',in_pack_x_y_z));
+        systemunit.insert(tsyssym.create('Unpack',in_unpack_x_y_z));
         systemunit.insert(tsyssym.create('Break',in_break));
         systemunit.insert(tsyssym.create('Exit',in_exit));
         systemunit.insert(tsyssym.create('Continue',in_continue));

+ 19 - 4
compiler/ptconst.pas

@@ -379,8 +379,17 @@ implementation
                                        end;
                                      arraydef :
                                        begin
-                                          len:=tarraydef(tvecnode(hp).left.resulttype.def).elesize;
-                                          base:=tarraydef(tvecnode(hp).left.resulttype.def).lowrange;
+                                          if not is_packed_array(tvecnode(hp).left.resulttype.def) then
+                                            begin
+                                              len:=tarraydef(tvecnode(hp).left.resulttype.def).elesize;
+                                              base:=tarraydef(tvecnode(hp).left.resulttype.def).lowrange;
+                                            end
+                                          else
+                                            begin
+                                              Message(parser_e_packed_dynamic_open_array);
+                                              len:=1;
+                                              base:=0;
+                                            end;
                                        end
                                      else
                                        Message(parser_e_illegal_expression);
@@ -631,6 +640,12 @@ implementation
                   consume(_NIL);
                   datalist.concat(Tai_const.Create_sym(nil));
                 end
+               { no packed array constants supported }
+               else if is_packed_array(t.def) then
+                 begin
+                   Message(type_e_no_const_packed_array);
+                   consume_all_until(_RKLAMMER);
+                 end
               else
               if try_to_consume(_LKLAMMER) then
                 begin
@@ -890,8 +905,8 @@ implementation
                   p:=comp_expr(true);
                   if p.nodetype<>niln then
                     begin
-                      Message(parser_e_type_const_not_possible);
-                      consume_all_until(_RKLAMMER);
+                      Message(type_e_no_const_packed_array);
+                      consume_all_until(_SEMICOLON);
                     end
                   else
                     begin

+ 20 - 6
compiler/ptype.pas

@@ -452,7 +452,7 @@ implementation
         end;
 
 
-      procedure array_dec;
+      procedure array_dec(is_packed: boolean);
         var
           lowval,
           highval   : TConstExprInt;
@@ -571,6 +571,8 @@ implementation
                      ap.elementtype.setdef(tarraydef.create(lowval,highval,arraytype));
                      ap:=tarraydef(ap.elementtype.def);
                    end;
+                 if is_packed then
+                   include(ap.arrayoptions,ado_IsBitPacked);
 
                   if token=_COMMA then
                     consume(_COMMA)
@@ -581,6 +583,8 @@ implementation
              end
            else
              begin
+                if is_packed then
+                  Message(parser_e_packed_dynamic_open_array);
                 ap:=tarraydef.create(0,-1,s32inttype);
                 include(ap.arrayoptions,ado_IsDynamicArray);
                 tt.setdef(ap);
@@ -589,7 +593,12 @@ implementation
            read_anon_type(tt2,true);
            { if no error, set element type }
            if assigned(ap) then
-             ap.setelementtype(tt2);
+             begin
+               ap.setelementtype(tt2);
+               if is_packed and
+                  tt2.def.needs_inittable then
+                 Message(type_e_no_packed_inittable);
+             end;
         end;
 
       var
@@ -599,6 +608,7 @@ implementation
         enumdupmsg, first : boolean;
         newtype    : ttypesym;
         oldlocalswitches : tlocalswitches;
+        bitpacking: boolean;
       begin
          tt.reset;
          case token of
@@ -668,7 +678,7 @@ implementation
               end;
             _ARRAY:
               begin
-                array_dec;
+                array_dec(false);
               end;
             _SET:
               begin
@@ -684,11 +694,15 @@ implementation
               begin
                 tt.setdef(record_dec);
               end;
-            _PACKED:
+            _PACKED,
+            _BITPACKED:
               begin
-                consume(_PACKED);
+                bitpacking :=
+                  (cs_bitpacking in aktlocalswitches) or
+                  (token = _BITPACKED);
+                consume(token);
                 if token=_ARRAY then
-                  array_dec
+                  array_dec(bitpacking)
                 else if token=_SET then
                   set_dec
                 else

+ 16 - 2
compiler/rautils.pas

@@ -887,7 +887,14 @@ Begin
               while assigned(harrdef.elementtype.def) and
                     (harrdef.elementtype.def.deftype=arraydef) do
                harrdef:=tarraydef(harrdef.elementtype.def);
-              SetSize(harrdef.elesize,false);
+              if not is_packed_array(harrdef) then
+                SetSize(harrdef.elesize,false)
+               else
+                 begin
+                   if (harrdef.elepackedbitsize mod 8) <> 0 then
+                     Message(asmr_e_packed_element);
+                   SetSize((harrdef.elepackedbitsize + 7) div 8,false);
+                 end;
             end;
         end;
         hasvar:=true;
@@ -1351,7 +1358,14 @@ Begin
                      while assigned(harrdef.elementtype.def) and
                            (harrdef.elementtype.def.deftype=arraydef) do
                       harrdef:=tarraydef(harrdef.elementtype.def);
-                     size:=harrdef.elesize;
+                     if not is_packed_array(harrdef) then
+                       size:=harrdef.elesize
+                     else
+                       begin
+                         if (harrdef.elepackedbitsize mod 8) <> 0 then
+                           Message(asmr_e_packed_element);
+                         size := (harrdef.elepackedbitsize + 7) div 8;
+                       end;
                    end;
                  recorddef :
                    st:=trecorddef(def).symtable;

+ 7 - 0
compiler/scandir.pas

@@ -1197,6 +1197,12 @@ implementation
       end;
 
 
+    procedure dir_bitpacking;
+      begin
+        do_localswitch(cs_bitpacking);
+      end;
+
+
 {****************************************************************************
                          Initialize Directives
 ****************************************************************************}
@@ -1216,6 +1222,7 @@ implementation
         AddDirective('ASMMODE',directive_all, @dir_asmmode);
         AddDirective('ASSERTIONS',directive_all, @dir_assertions);
         AddDirective('BOOLEVAL',directive_all, @dir_booleval);
+        AddDirective('BITPACKING',directive_all, @dir_bitpacking);
         AddDirective('CALLING',directive_all, @dir_calling);
         AddDirective('CHECKPOINTER',directive_all, @dir_checkpointer);
         AddDirective('CODEALIGN',directive_all, @dir_codealign);

+ 8 - 0
compiler/scanner.pas

@@ -302,6 +302,14 @@ implementation
                exclude(initlocalswitches,cs_ansistrings);
             end;
 
+           { turn on bitpacking for mode macpas }
+           if (m_mac in aktmodeswitches) then
+             begin
+               include(aktlocalswitches,cs_bitpacking);
+               if changeinit then
+                 include(initlocalswitches,cs_bitpacking);
+             end;
+
            { support goto/label by default in delphi/tp7/mac modes }
            if ([m_delphi,m_tp7,m_mac] * aktmodeswitches <> []) then
              begin

+ 2 - 1
compiler/symconst.pas

@@ -315,7 +315,8 @@ type
     ado_IsVariant,
     ado_IsConstructor,
     ado_IsArrayOfConst,
-    ado_IsConstString
+    ado_IsConstString,
+    ado_IsBitPacked
   );
   tarraydefoptions=set of tarraydefoption;
 

+ 120 - 13
compiler/symdef.pas

@@ -334,6 +334,7 @@ interface
           _elementtype : ttype;
        public
           function elesize : aint;
+          function elepackedbitsize : aint;
           function elecount : aint;
           constructor create_from_pointer(const elemt : ttype);
           constructor create(l,h : aint;const t : ttype);
@@ -365,6 +366,7 @@ interface
           function  gettypename:string;override;
           function alignment:shortint;override;
           procedure setsize;
+          function  packedbitsize: aint; override;
           function getvartype : longint;override;
           { rtti }
           procedure write_rtti_data(rt:trttitype);override;
@@ -603,6 +605,7 @@ interface
           function  gettypename:string;override;
           function  is_publishable : boolean;override;
           procedure calcsavesize;
+          function  packedbitsize: aint; override;
           procedure setmax(_max:aint);
           procedure setmin(_min:aint);
           function  min:aint;
@@ -1463,6 +1466,27 @@ implementation
       end;
 
 
+    function tenumdef.packedbitsize: aint;
+      var
+        power: longint;
+      begin
+        result := 0;
+        if (minval < 0) then
+          result := inherited packedbitsize
+        else
+          begin
+            if (maxval <= 1) then
+              result := 1
+            else
+              begin
+                { 256 must become 512 etc. }
+                nextpowerof2(maxval+1,power);
+                result := power;
+              end;
+          end;
+      end;
+
+
     procedure tenumdef.setmax(_max:aint);
       begin
         maxval:=_max;
@@ -1656,6 +1680,31 @@ implementation
       end;
 
 
+    function torddef.packedbitsize: aint;
+      var
+        power: longint;
+      begin
+        result := 0;
+        if typ = uvoid then
+          exit;
+        if (low < 0) then
+          result := inherited packedbitsize
+        else
+          begin
+            if (high <= 1) then
+              result := 1
+            else if (typ = u64bit) then
+              result := 64
+            else
+              begin
+                { 256 must become 512 etc. }
+                nextpowerof2(high+1,power);
+                result := power;
+              end;
+          end;
+      end;
+
+
     function torddef.getvartype : longint;
       const
         basetype2vartype : array[tbasetype] of longint = (
@@ -2470,10 +2519,20 @@ implementation
 
     function tarraydef.elesize : aint;
       begin
+        if (ado_IsBitPacked in arrayoptions) then
+          internalerror(2006080101);
         elesize:=_elementtype.def.size;
       end;
 
 
+    function tarraydef.elepackedbitsize : aint;
+      begin
+        if not(ado_IsBitPacked in arrayoptions) then
+          internalerror(2006080102);
+        result:=_elementtype.def.packedbitsize;
+      end;
+
+
     function tarraydef.elecount : aint;
       var
         qhigh,qlow : qword;
@@ -2508,21 +2567,42 @@ implementation
             size:=sizeof(aint);
             exit;
           end;
+
         { Tarraydef.size may never be called for an open array! }
         if highrange<lowrange then
           internalerror(99080501);
-        cachedelesize:=elesize;
+        if not (ado_IsBitPacked in arrayoptions) then
+          cachedelesize:=elesize
+        else
+          cachedelesize := elepackedbitsize;
         cachedelecount:=elecount;
+
+        if (cachedelesize = 0) then
+          begin
+            size := 0;
+            exit;
+          end;
+
+        if (cachedelecount = -1) then
+          begin
+            size := -1;
+            exit;
+          end;
+
         { prevent overflow, return -1 to indicate overflow }
-        if (cachedelesize <> 0) and
-           (
-            (cachedelecount < 0) or
-            ((high(aint) div cachedelesize) < cachedelecount) or
-            { also lowrange*elesize must be < high(aint) to prevent overflow when
-              accessing the array, see ncgmem (PFV) }
-            ((high(aint) div cachedelesize) < abs(lowrange))
-           ) then
-          result:=-1
+        { also make sure we don't need 64/128 bit arithmetic to calculate offsets }
+        if (cachedelecount > high(aint)) or
+           ((high(aint) div cachedelesize) < cachedelecount) or
+           { also lowrange*elesize must be < high(aint) to prevent overflow when
+             accessing the array, see ncgmem (PFV) }
+           ((high(aint) div cachedelesize) < abs(lowrange)) then
+          begin
+            result:=-1;
+            exit;
+          end;
+
+        if (ado_IsBitPacked in arrayoptions) then
+          size:=align(cachedelesize * cachedelecount,alignment) div 8
         else
           result:=cachedelesize*cachedelecount;
       end;
@@ -2548,8 +2628,26 @@ implementation
            ((elementtype.def.deftype=objectdef) and
              is_object(elementtype.def)) then
            alignment:=elementtype.def.alignment
+         else if not (ado_IsBitPacked in arrayoptions) then
+           alignment:=size_2_align(elesize)
          else
-           alignment:=size_2_align(elesize);
+           case elepackedbitsize of
+             1,2,4,8:
+               alignment := 1;
+             { 10 bits can never be split over 3 bytes via 1-8-1, because it }
+             { always starts at a multiple of 10 bits. Same for the others.  }
+             3,5,7,9,10,12,16:
+               alignment := 2;
+{$ifdef cpu64bit}
+             11,13,14,15,17..26,28,32:
+               alignment := 4;
+             else
+               alignment := 8;
+{$else cpu64bit}
+             else
+               alignment := 4;
+{$endif cpu64bit}
+           end;
       end;
 
 
@@ -2567,6 +2665,12 @@ implementation
 
     procedure tarraydef.write_rtti_data(rt:trttitype);
       begin
+         if ado_IsBitPacked in arrayoptions then
+           begin
+             current_asmdata.asmlists[al_rtti].concat(tai_const.create_8bit(tkUnknown));
+             write_rtti_name;
+             exit;
+           end;
          if ado_IsDynamicArray in arrayoptions then
            current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkdynarray))
          else
@@ -2602,10 +2706,13 @@ implementation
            gettypename:='Array Of '+elementtype.def.typename
          else
            begin
+              result := '';
+              if (ado_IsBitPacked in arrayoptions) then
+                result:='Packed ';
               if rangetype.def.deftype=enumdef then
-                gettypename:='Array['+rangetype.def.typename+'] Of '+elementtype.def.typename
+                result:=result+'Array['+rangetype.def.typename+'] Of '+elementtype.def.typename
               else
-                gettypename:='Array['+tostr(lowrange)+'..'+
+                result:=result+'Array['+tostr(lowrange)+'..'+
                   tostr(highrange)+'] Of '+elementtype.def.typename
            end;
       end;

+ 11 - 4
compiler/symtype.pas

@@ -86,6 +86,7 @@ interface
          function  mangledparaname:string;
          function  getmangledparaname:string;virtual;
          function  size:aint;virtual;abstract;
+         function  packedbitsize:aint;virtual;
          function  alignment:shortint;virtual;abstract;
          function  getvartype:longint;virtual;abstract;
          function  getparentdef:tdef;virtual;
@@ -298,10 +299,16 @@ implementation
       end;
 
 
-   function  tdef.is_related(def:tdef):boolean;
-     begin
-       result:=false;
-     end;
+    function tdef.is_related(def:tdef):boolean;
+      begin
+        result:=false;
+      end;
+
+
+    function tdef.packedbitsize:aint;
+      begin
+        result:=size * 8;
+      end;
 
 
 {****************************************************************************

+ 2 - 0
compiler/tokens.pas

@@ -214,6 +214,7 @@ type
     _SAFECALL,
     _SYSVBASE,
     _ASSEMBLER,
+    _BITPACKED,
     _INHERITED,
     _INTERFACE,
     _INTERRUPT,
@@ -461,6 +462,7 @@ const
       (str:'SAFECALL'      ;special:false;keyword:m_none;op:NOTOKEN),
       (str:'SYSVBASE'      ;special:false;keyword:m_none;op:NOTOKEN),   { Syscall variation on MorphOS }
       (str:'ASSEMBLER'     ;special:false;keyword:m_none;op:NOTOKEN),
+      (str:'BITPACKED'     ;special:false;keyword:m_all;op:NOTOKEN),
       (str:'INHERITED'     ;special:false;keyword:m_all;op:NOTOKEN),
       (str:'INTERFACE'     ;special:false;keyword:m_all;op:NOTOKEN),
       (str:'INTERRUPT'     ;special:false;keyword:m_none;op:NOTOKEN),

+ 2 - 0
rtl/inc/innr.inc

@@ -67,6 +67,8 @@ const
    fpc_in_get_frame         = 56;
    fpc_in_get_caller_addr   = 57;
    fpc_in_get_caller_frame  = 58;
+   fpc_in_pack_x_y_z        = 59;
+   fpc_in_unpack_x_y_z      = 60;
 
 { Internal constant functions }
    fpc_in_const_sqr        = 100;