diff options
author | jonas <jonas@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2007-05-19 17:15:15 +0000 |
---|---|---|
committer | jonas <jonas@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2007-05-19 17:15:15 +0000 |
commit | e59661ad922265f08814f2e195d1cd852b4ad752 (patch) | |
tree | 88027d8f1f9693d64d283a3bc4640407ff1891f0 /rtl/powerpc | |
parent | 9ac38fb027825418603ebf4b20b928855f41fd7b (diff) | |
download | fpc-e59661ad922265f08814f2e195d1cd852b4ad752.tar.gz |
* new internal set format for big endian systems. Advantages:
* varsets ({$packset x}) are now supported on big endian targets
* gdb now displays sets properly on big endian systems
* cleanup of generic set code (in, include/exclude, helpers), all
based on "bitpacked array[] of 0..1" now
* there are no helpers available yet to convert sets from the old to
the new format, because the set format will change again slightly
in the near future (so that e.g. a set of 24..31 will be stored in
1 byte), and creating two classes of set conversion helpers would
confuse things (i.e., it's not recommended to use trunk currently for
programs which load sets stored to disk by big endian programs compiled
by previous FPC versions)
* cross-endian compiling has been tested and still works, but one case
is not supported: compiling a compiler for a different endianess
using a starting compiler from before the current revision (so first
cycle natively, and then use the newly created compiler to create a
cross-compiler)
git-svn-id: http://svn.freepascal.org/svn/fpc/trunk@7395 3ad0048d-3df7-0310-abae-a5850022a9f2
Diffstat (limited to 'rtl/powerpc')
-rw-r--r-- | rtl/powerpc/set.inc | 227 |
1 files changed, 37 insertions, 190 deletions
diff --git a/rtl/powerpc/set.inc b/rtl/powerpc/set.inc index 4fe6e5247c..d39e72dbb1 100644 --- a/rtl/powerpc/set.inc +++ b/rtl/powerpc/set.inc @@ -53,6 +53,7 @@ asm stw r0,24(r3) stw r0,28(r3) +{$ifndef FPC_NEW_BIGENDIAN_SETS} // r0 := 1 shl r4[27-31] -> bit index in dword (rotate instructions // with count in register only consider lower 5 bits of this register) li r0,1 @@ -62,9 +63,17 @@ asm // (((b div 8) div 4)*4= (b div 8) and not(3)) // r5 := (r4 rotl(32-3)) and (0x01ffffff8) rlwinm r4,r4,31-3+1,3,31-2 - // store the result stwx r0,r3,r4 +{$else} + { must be done byte- instead of dword-based } + rlwinm r5,r4,0,31-3+1,31 + li r0,0x80 + srw r0,r0,r5 + srwi r4,r4,3 + // store the result + stbx r0,r3,r4 +{$endif} end; @@ -86,6 +95,7 @@ asm stfd f2,16(r3) stfd f3,24(r3) +{$ifndef FPC_NEW_BIGENDIAN_SETS} // get the index of the correct *dword* in the set // r0 := (r5 rotl(32-3)) and (0x0fffffff8) rlwinm r0,r5,31-3+1,3,31-2 @@ -99,6 +109,17 @@ asm or r5,r4,r5 // store result stw r5,0(r3) +{$else} + { must be done byte- instead of dword-based } + srwi r6,r5,3 + lbzx r7,r6,r3 + rlwinm r5,r5,0,31-3+1,31 + li r0,0x80 + srw r0,r0,r5 + or r7,r7,r0 + // store the result + stbx r7,r6,r3 +{$endif} end; @@ -120,6 +141,7 @@ asm stfd f1,8(r3) stfd f2,16(r3) stfd f3,24(r3) +{$ifndef FPC_NEW_BIGENDIAN_SETS} // get the index of the correct *dword* in the set // r0 := (r4 rotl(32-3)) and (0x0fffffff8) rlwinm r0,r5,31-3+1,3,31-2 @@ -132,9 +154,22 @@ asm andc r5,r4,r5 // store result stw r4,0(r3) +{$else} + { must be done byte- instead of dword-based } + srwi r6,r5,3 + lbzx r7,r6,r3 + rlwinm r5,r5,0,31-3+1,31 + li r0,0x80 + srw r0,r0,r5 + andc r7,r7,r0 + // store the result + stbx r7,r6,r3 +{$endif} end; +{$ifndef FPC_NEW_BIGENDIAN_SETS} + {$define FPC_SYSTEM_HAS_FPC_SET_SET_RANGE} function fpc_set_set_range(const orgset: fpc_normal_set; l,h : byte): fpc_normal_set;assembler; compilerproc; { @@ -196,29 +231,7 @@ asm stw r5,0(r3) // store to set .Lset_range_exit: end; - - -{$define FPC_SYSTEM_HAS_FPC_SET_IN_BYTE} -function fpc_set_in_byte(const p: fpc_normal_set; b : byte): boolean;compilerproc;assembler;[public,alias:'FPC_SET_IN_BYTE']; -{ - tests if the element b is in the set p, the **zero** flag is cleared if it's present - - on entry: p in r3, b in r4 -} -asm - // get the index of the correct *dword* in the set - // r0 := (r4 rotl(32-3)) and (0x0fffffff8) - rlwinm r0,r4,31-3+1,3,31-2 - - // load dword in which the bit has to be tested - lwzx r3,r3,r0 - - // r4 := 32 - r4 (no problem if r4 > 32, the rlwnm next does a mod 32) - subfic r4,r4,32 - // r3 := (r3 shr (r4 mod 32)) and 1 - rlwnm r3,r3,r4,31,31 -end; - +{$endif} {$define FPC_SYSTEM_HAS_FPC_SET_ADD_SETS} @@ -354,169 +367,3 @@ asm cntlzw r3,r0 srwi. r3,r3,5 end; - - - -{$ifdef LARGESETS} - -procedure do_set(p : pointer;b : word);assembler;[public,alias:'FPC_SET_SET_WORD']; -{ - sets the element b in set p works for sets larger than 256 elements - not yet use by the compiler so -} -asm - pushl %eax - movl p,%edi - movw b,%ax - andl $0xfff8,%eax - shrl $3,%eax - addl %eax,%edi - movb 12(%ebp),%al - andl $7,%eax - btsl %eax,(%edi) - popl %eax -end; - - -procedure do_in(p : pointer;b : word);assembler;[public,alias:'FPC_SET_IN_WORD']; -{ - tests if the element b is in the set p the carryflag is set if it present - works for sets larger than 256 elements -} -asm - pushl %eax - movl p,%edi - movw b,%ax - andl $0xfff8,%eax - shrl $3,%eax - addl %eax,%edi - movb 12(%ebp),%al - andl $7,%eax - btl %eax,(%edi) - popl %eax -end; - - -procedure add_sets(set1,set2,dest : pointer;size : longint);assembler;[public,alias:'FPC_SET_ADD_SETS_SIZE']; -{ - adds set1 and set2 into set dest size is the number of bytes in the set -} -asm - movl set1,%esi - movl set2,%ebx - movl dest,%edi - movl size,%ecx - .LMADDSETSIZES1: - lodsl - orl (%ebx),%eax - stosl - addl $4,%ebx - decl %ecx - jnz .LMADDSETSIZES1 -end; - - -procedure mul_sets(set1,set2,dest : pointer;size : longint);assembler;[public,alias:'FPC_SET_MUL_SETS_SIZE']; -{ - multiplies (i.E. takes common elements of) set1 and set2 result put in - dest size is the number of bytes in the set -} -asm - movl set1,%esi - movl set2,%ebx - movl dest,%edi - movl size,%ecx - .LMMULSETSIZES1: - lodsl - andl (%ebx),%eax - stosl - addl $4,%ebx - decl %ecx - jnz .LMMULSETSIZES1 -end; - - -procedure sub_sets(set1,set2,dest : pointer;size : longint);assembler;[public,alias:'FPC_SET_SUB_SETS_SIZE']; -asm - movl set1,%esi - movl set2,%ebx - movl dest,%edi - movl size,%ecx - .LMSUBSETSIZES1: - lodsl - movl (%ebx),%edx - notl %edx - andl %edx,%eax - stosl - addl $4,%ebx - decl %ecx - jnz .LMSUBSETSIZES1 -end; - - -procedure sym_sub_sets(set1,set2,dest : pointer;size : longint);assembler;[public,alias:'FPC_SET_SYMDIF_SETS_SIZE']; -{ - computes the symetric diff from set1 to set2 result in dest -} -asm - movl set1,%esi - movl set2,%ebx - movl dest,%edi - movl size,%ecx - .LMSYMDIFSETSIZE1: - lodsl - movl (%ebx),%edx - xorl %edx,%eax - stosl - addl $4,%ebx - decl %ecx - jnz LMSYMDIFSETSIZE1 -end; - - -procedure comp_sets(set1,set2 : pointer;size : longint);assembler;[public,alias:'FPC_SET_COMP_SETS_SIZE']; -asm - movl set1,%esi - movl set2,%edi - movl size,%ecx - LMCOMPSETSIZES1: - lodsl - movl (%edi),%edx - cmpl %edx,%eax - jne LMCOMPSETSIZEEND - addl $4,%edi - decl %ecx - jnz LMCOMPSETSIZES1 - { we are here only if the two sets are equal - we have zero flag set, and that what is expected } - LMCOMPSETSIZEEND: -end; - -{$IfNDef NoSetInclusion} -procedure contains_sets(set1,set2 : pointer; size: longint);assembler;[public,alias:'FPC_SET_CONTAINS_SETS']; -{ - on exit, zero flag is set if set1 <= set2 (set2 contains set1) -} -asm - movl set1,%esi - movl set2,%edi - movl size,%ecx - LMCONTAINSSETS2: - movl (%esi),%eax - movl (%edi),%edx - andl %eax,%edx - cmpl %edx,%eax {set1 and set2 = set1?} - jne LMCONTAINSSETEND2 - addl $4,%esi - addl $4,%edi - decl %ecx - jnz LMCONTAINSSETS2 - { we are here only if set2 contains set1 - we have zero flag set, and that what is expected } - LMCONTAINSSETEND2: -end; -{$EndIf NoSetInclusion} - - -{$endif LARGESET} - |