; Copyright (C) 2011-2017 Free Software Foundation, Inc. ; Contributed by Red Hat. ; ; This file is free software; you can redistribute it and/or modify it ; under the terms of the GNU General Public License as published by the ; Free Software Foundation; either version 3, or (at your option) any ; later version. ; ; This file is distributed in the hope that it will be useful, but ; WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ; General Public License for more details. ; ; Under Section 7 of GPL version 3, you are granted additional ; permissions described in the GCC Runtime Library Exception, version ; 3.1, as published by the Free Software Foundation. ; ; You should have received a copy of the GNU General Public License and ; a copy of the GCC Runtime Library Exception along with this program; ; see the files COPYING3 and COPYING.RUNTIME respectively. If not, see ; . #include "vregs.h" .text ;; int __cmpsi2 (signed long A, signed long B) ;; ;; Performs a signed comparison of A and B. ;; If A is less than B it returns 0. If A is greater ;; than B it returns 2. If they are equal it returns 1. START_FUNC ___cmpsi2 ;; A is at [sp+4] ;; B is at [sp+8] ;; Result put in R8 ;; Initialise default return value. onew bc ;; Compare the high words. movw ax, [sp + 10] movw de, ax movw ax, [sp + 6] cmpw ax, de skz br !!.Lconvert_to_signed .Lcompare_bottom_words: ;; The top words are equal - compare the bottom words. ;; Note - code from __ucmpsi2 branches into here. movw ax, [sp + 8] movw de, ax movw ax, [sp + 4] cmpw ax, de sknz br !!.Lless_than_or_greater_than ;; The words are equal - return 1. ;; Note - we could branch to the return code at the end of the ;; function but a branch instruction takes 4 bytes, and the ;; return sequence itself is only 4 bytes long... movw ax, bc movw r8, ax ret .Lconvert_to_signed: ;; The top words are different. Unfortunately the comparison ;; is always unsigned, so to get a signed result we XOR the CY ;; flag with the top bits of AX and DE. xor1 cy, a.7 mov a, d xor1 cy, a.7 ;; Fall through. .Lless_than_or_greater_than: ;; We now have a signed less than/greater than result in CY. ;; Return 0 for less than, 2 for greater than. ;; Note - code from __ucmpsi2 branches into here. incw bc sknc clrw bc ;; Get the result value, currently in BC, into r8 movw ax, bc movw r8, ax ret END_FUNC ___cmpsi2 ;; ------------------------------------------------------ ;; int __ucmpsi2 (unsigned long A, unsigned long B) ;; ;; Performs an unsigned comparison of A and B. ;; If A is less than B it returns 0. If A is greater ;; than B it returns 2. If they are equal it returns 1. START_FUNC ___ucmpsi2 ;; A is at [sp+4] ;; B is at [sp+8] ;; Result put in R8..R9 ;; Initialise default return value. onew bc ;; Compare the high words. movw ax, [sp + 10] movw de, ax movw ax, [sp + 6] cmpw ax, de skz ;; Note: These branches go into the __cmpsi2 code! br !!.Lless_than_or_greater_than br !!.Lcompare_bottom_words END_FUNC ___ucmpsi2 ;; ------------------------------------------------------ ;; signed int __gcc_bcmp (const unsigned char *s1, const unsigned char *s2, size_t size) ;; Result is negative if S1 is less than S2, ;; positive if S1 is greater, 0 if S1 and S2 are equal. START_FUNC __gcc_bcmp ;; S1 is at [sp+4] ;; S2 is at [sp+6] ;; SIZE is at [sp+8] ;; Result in r8/r9 movw r10, #0 1: ;; Compare R10 against the SIZE parameter movw ax, [sp+8] subw ax, r10 sknz br !!1f ;; Load S2[r10] into R8 movw ax, [sp+6] addw ax, r10 movw hl, ax mov a, [hl] mov r8, a ;; Load S1[r10] into A movw ax, [sp+4] addw ax, r10 movw hl, ax mov a, [hl] ;; Increment offset incw r10 ;; Compare loaded bytes cmp a, r8 sknz br !!1b ;; They differ. Subtract *S2 from *S1 and return as the result. mov x, a mov a, #0 mov r9, #0 subw ax, r8 1: movw r8, ax ret END_FUNC __gcc_bcmp