Text file src/internal/bytealg/compare_ppc64x.s

     1  // Copyright 2018 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build ppc64 || ppc64le
     6  
     7  #include "go_asm.h"
     8  #include "textflag.h"
     9  
    10  TEXT ·Compare<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-56
    11  #ifdef GOEXPERIMENT_regabiargs
    12  // incoming:
    13  // R3 a addr -> R5
    14  // R4 a len  -> R3
    15  // R5 a cap unused
    16  // R6 b addr -> R6
    17  // R7 b len  -> R4
    18  // R8 b cap unused
    19  	MOVD	R3, R5
    20  	MOVD	R4, R3
    21  	MOVD	R7, R4
    22  #else
    23  	MOVD	a_base+0(FP), R5
    24  	MOVD	b_base+24(FP), R6
    25  	MOVD	a_len+8(FP), R3
    26  	MOVD	b_len+32(FP), R4
    27  	MOVD	$ret+48(FP), R7
    28  #endif
    29  	CMP     R5,R6,CR7
    30  	CMP	R3,R4,CR6
    31  	BEQ	CR7,equal
    32  #ifdef	GOARCH_ppc64le
    33  	BR	cmpbodyLE<>(SB)
    34  #else
    35  	BR      cmpbodyBE<>(SB)
    36  #endif
    37  equal:
    38  	BEQ	CR6,done
    39  	MOVD	$1, R8
    40  	BGT	CR6,greater
    41  	NEG	R8
    42  greater:
    43  #ifdef GOEXPERIMENT_regabiargs
    44  	MOVD	R8, R3
    45  #else
    46  	MOVD	R8, (R7)
    47  #endif
    48  	RET
    49  done:
    50  #ifdef GOEXPERIMENT_regabiargs
    51  	MOVD	$0, R3
    52  #else
    53  	MOVD	$0, (R7)
    54  #endif
    55  	RET
    56  
    57  TEXT runtime·cmpstring<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-40
    58  #ifdef GOEXPERIMENT_regabiargs
    59  // incoming:
    60  // R3 a addr -> R5
    61  // R4 a len  -> R3
    62  // R5 b addr -> R6
    63  // R6 b len  -> R4
    64  	MOVD	R6, R7
    65  	MOVD	R5, R6
    66  	MOVD	R3, R5
    67  	MOVD	R4, R3
    68  	MOVD	R7, R4
    69  #else
    70  	MOVD	a_base+0(FP), R5
    71  	MOVD	b_base+16(FP), R6
    72  	MOVD	a_len+8(FP), R3
    73  	MOVD	b_len+24(FP), R4
    74  	MOVD	$ret+32(FP), R7
    75  #endif
    76  	CMP     R5,R6,CR7
    77  	CMP	R3,R4,CR6
    78  	BEQ	CR7,equal
    79  #ifdef	GOARCH_ppc64le
    80  	BR	cmpbodyLE<>(SB)
    81  #else
    82  	BR      cmpbodyBE<>(SB)
    83  #endif
    84  equal:
    85  	BEQ	CR6,done
    86  	MOVD	$1, R8
    87  	BGT	CR6,greater
    88  	NEG	R8
    89  greater:
    90  #ifdef GOEXPERIMENT_regabiargs
    91  	MOVD	R8, R3
    92  #else
    93  	MOVD	R8, (R7)
    94  #endif
    95  	RET
    96  
    97  done:
    98  #ifdef GOEXPERIMENT_regabiargs
    99  	MOVD	$0, R3
   100  #else
   101  	MOVD	$0, (R7)
   102  #endif
   103  	RET
   104  
   105  // Do an efficient memcmp for ppc64le
   106  // R3 = a len
   107  // R4 = b len
   108  // R5 = a addr
   109  // R6 = b addr
   110  // R7 = addr of return value if not regabi
   111  TEXT cmpbodyLE<>(SB),NOSPLIT|NOFRAME,$0-0
   112  	MOVD	R3,R8		// set up length
   113  	CMP	R3,R4,CR2	// unequal?
   114  	BC	12,8,setuplen	// BLT CR2
   115  	MOVD	R4,R8		// use R4 for comparison len
   116  setuplen:
   117  	MOVD	R8,CTR		// set up loop counter
   118  	CMP	R8,$8		// only optimize >=8
   119  	BLT	simplecheck
   120  	DCBT	(R5)		// cache hint
   121  	DCBT	(R6)
   122  	CMP	R8,$32		// optimize >= 32
   123  	MOVD	R8,R9
   124  	BLT	setup8a		// 8 byte moves only
   125  setup32a:
   126  	SRADCC	$5,R8,R9	// number of 32 byte chunks
   127  	MOVD	R9,CTR
   128  
   129          // Special processing for 32 bytes or longer.
   130          // Loading this way is faster and correct as long as the
   131  	// doublewords being compared are equal. Once they
   132  	// are found unequal, reload them in proper byte order
   133  	// to determine greater or less than.
   134  loop32a:
   135  	MOVD	0(R5),R9	// doublewords to compare
   136  	MOVD	0(R6),R10	// get 4 doublewords
   137  	MOVD	8(R5),R14
   138  	MOVD	8(R6),R15
   139  	CMPU	R9,R10		// bytes equal?
   140  	MOVD	$0,R16		// set up for cmpne
   141  	BNE	cmpne		// further compare for LT or GT
   142  	MOVD	16(R5),R9	// get next pair of doublewords
   143  	MOVD	16(R6),R10
   144  	CMPU	R14,R15		// bytes match?
   145  	MOVD	$8,R16		// set up for cmpne
   146  	BNE	cmpne		// further compare for LT or GT
   147  	MOVD	24(R5),R14	// get next pair of doublewords
   148  	MOVD    24(R6),R15
   149  	CMPU	R9,R10		// bytes match?
   150  	MOVD	$16,R16		// set up for cmpne
   151  	BNE	cmpne		// further compare for LT or GT
   152  	MOVD	$-8,R16		// for cmpne, R5,R6 already inc by 32
   153  	ADD	$32,R5		// bump up to next 32
   154  	ADD	$32,R6
   155  	CMPU    R14,R15		// bytes match?
   156  	BC	8,2,loop32a	// br ctr and cr
   157  	BNE	cmpne
   158  	ANDCC	$24,R8,R9	// Any 8 byte chunks?
   159  	BEQ	leftover	// and result is 0
   160  setup8a:
   161  	SRADCC	$3,R9,R9	// get the 8 byte count
   162  	BEQ	leftover	// shifted value is 0
   163  	MOVD	R9,CTR		// loop count for doublewords
   164  loop8:
   165  	MOVDBR	(R5+R0),R9	// doublewords to compare
   166  	MOVDBR	(R6+R0),R10	// LE compare order
   167  	ADD	$8,R5
   168  	ADD	$8,R6
   169  	CMPU	R9,R10		// match?
   170  	BC	8,2,loop8	// bt ctr <> 0 && cr
   171  	BGT	greater
   172  	BLT	less
   173  leftover:
   174  	ANDCC	$7,R8,R9	// check for leftover bytes
   175  	MOVD	R9,CTR		// save the ctr
   176  	BNE	simple		// leftover bytes
   177  	BC	12,10,equal	// test CR2 for length comparison
   178  	BC	12,8,less
   179  	BR	greater
   180  simplecheck:
   181  	CMP	R8,$0		// remaining compare length 0
   182  	BNE	simple		// do simple compare
   183  	BC	12,10,equal	// test CR2 for length comparison
   184  	BC	12,8,less	// 1st len < 2nd len, result less
   185  	BR	greater		// 1st len > 2nd len must be greater
   186  simple:
   187  	MOVBZ	0(R5), R9	// get byte from 1st operand
   188  	ADD	$1,R5
   189  	MOVBZ	0(R6), R10	// get byte from 2nd operand
   190  	ADD	$1,R6
   191  	CMPU	R9, R10
   192  	BC	8,2,simple	// bc ctr <> 0 && cr
   193  	BGT	greater		// 1st > 2nd
   194  	BLT	less		// 1st < 2nd
   195  	BC	12,10,equal	// test CR2 for length comparison
   196  	BC	12,9,greater	// 2nd len > 1st len
   197  	BR	less		// must be less
   198  cmpne:				// only here is not equal
   199  	MOVDBR	(R5+R16),R8	// reload in reverse order
   200  	MOVDBR	(R6+R16),R9
   201  	CMPU	R8,R9		// compare correct endianness
   202  	BGT	greater		// here only if NE
   203  less:
   204  	MOVD	$-1,R3
   205  #ifndef GOEXPERIMENT_regabiargs
   206  	MOVD	R3,(R7)		// return value if A < B
   207  #endif
   208  	RET
   209  equal:
   210  #ifdef GOEXPERIMENT_regabiargs
   211  	MOVD	$0, R3
   212  #else
   213  	MOVD	$0,(R7)		// return value if A == B
   214  #endif
   215  	RET
   216  greater:
   217  	MOVD	$1,R3
   218  #ifndef GOEXPERIMENT_regabiargs
   219  	MOVD	R3,(R7)		// return value if A > B
   220  #endif
   221  	RET
   222  
   223  // Do an efficient memcmp for ppc64 (BE)
   224  // R3 = a len
   225  // R4 = b len
   226  // R5 = a addr
   227  // R6 = b addr
   228  // R7 = addr of return value
   229  TEXT cmpbodyBE<>(SB),NOSPLIT|NOFRAME,$0-0
   230  	MOVD	R3,R8		// set up length
   231  	CMP	R3,R4,CR2	// unequal?
   232  	BC	12,8,setuplen	// BLT CR2
   233  	MOVD	R4,R8		// use R4 for comparison len
   234  setuplen:
   235  	MOVD	R8,CTR		// set up loop counter
   236  	CMP	R8,$8		// only optimize >=8
   237  	BLT	simplecheck
   238  	DCBT	(R5)		// cache hint
   239  	DCBT	(R6)
   240  	CMP	R8,$32		// optimize >= 32
   241  	MOVD	R8,R9
   242  	BLT	setup8a		// 8 byte moves only
   243  
   244  setup32a:
   245  	SRADCC	$5,R8,R9	// number of 32 byte chunks
   246  	MOVD	R9,CTR
   247  loop32a:
   248  	MOVD	0(R5),R9	// doublewords to compare
   249  	MOVD	0(R6),R10	// get 4 doublewords
   250  	MOVD	8(R5),R14
   251  	MOVD	8(R6),R15
   252  	CMPU	R9,R10		// bytes equal?
   253  	BLT	less		// found to be less
   254  	BGT	greater		// found to be greater
   255  	MOVD	16(R5),R9	// get next pair of doublewords
   256  	MOVD	16(R6),R10
   257  	CMPU	R14,R15		// bytes match?
   258  	BLT	less		// found less
   259  	BGT	greater		// found greater
   260  	MOVD	24(R5),R14	// get next pair of doublewords
   261  	MOVD	24(R6),R15
   262  	CMPU	R9,R10		// bytes match?
   263  	BLT	less		// found to be less
   264  	BGT	greater		// found to be greater
   265  	ADD	$32,R5		// bump up to next 32
   266  	ADD	$32,R6
   267  	CMPU	R14,R15		// bytes match?
   268  	BC	8,2,loop32a	// br ctr and cr
   269  	BLT	less		// with BE, byte ordering is
   270  	BGT	greater		// good for compare
   271  	ANDCC	$24,R8,R9	// Any 8 byte chunks?
   272  	BEQ	leftover	// and result is 0
   273  setup8a:
   274  	SRADCC	$3,R9,R9	// get the 8 byte count
   275  	BEQ	leftover	// shifted value is 0
   276  	MOVD	R9,CTR		// loop count for doublewords
   277  loop8:
   278  	MOVD	(R5),R9
   279  	MOVD	(R6),R10
   280  	ADD	$8,R5
   281  	ADD	$8,R6
   282  	CMPU	R9,R10		// match?
   283  	BC	8,2,loop8	// bt ctr <> 0 && cr
   284  	BGT	greater
   285  	BLT	less
   286  leftover:
   287  	ANDCC	$7,R8,R9	// check for leftover bytes
   288  	MOVD	R9,CTR		// save the ctr
   289  	BNE	simple		// leftover bytes
   290  	BC	12,10,equal	// test CR2 for length comparison
   291  	BC	12,8,less
   292  	BR	greater
   293  simplecheck:
   294  	CMP	R8,$0		// remaining compare length 0
   295  	BNE	simple		// do simple compare
   296  	BC	12,10,equal	// test CR2 for length comparison
   297  	BC 	12,8,less	// 1st len < 2nd len, result less
   298  	BR	greater		// same len, must be equal
   299  simple:
   300  	MOVBZ	0(R5),R9	// get byte from 1st operand
   301  	ADD	$1,R5
   302  	MOVBZ	0(R6),R10	// get byte from 2nd operand
   303  	ADD	$1,R6
   304  	CMPU	R9,R10
   305  	BC	8,2,simple	// bc ctr <> 0 && cr
   306  	BGT	greater		// 1st > 2nd
   307  	BLT	less		// 1st < 2nd
   308  	BC	12,10,equal	// test CR2 for length comparison
   309  	BC	12,9,greater	// 2nd len > 1st len
   310  less:
   311  	MOVD	$-1,R3
   312  #ifndef GOEXPERIMENT_regabiargs
   313  	MOVD    R3,(R7)		// return value if A < B
   314  #endif
   315  	RET
   316  equal:
   317  #ifdef GOEXPERIMENT_regabiargs
   318  	MOVD	$0, R3
   319  #else
   320  	MOVD    $0,(R7)		// return value if A == B
   321  #endif
   322  	RET
   323  greater:
   324  	MOVD	$1,R3
   325  #ifndef GOEXPERIMENT_regabiargs
   326  	MOVD	R3,(R7)		// return value if A > B
   327  #endif
   328  	RET
   329  

View as plain text