diff options
Diffstat (limited to 'libgcc/config/rl78/cmpsi2.S')
-rw-r--r-- | libgcc/config/rl78/cmpsi2.S | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/libgcc/config/rl78/cmpsi2.S b/libgcc/config/rl78/cmpsi2.S new file mode 100644 index 0000000000..20899973cc --- /dev/null +++ b/libgcc/config/rl78/cmpsi2.S @@ -0,0 +1,172 @@ +; 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 +; <http://www.gnu.org/licenses/>. + + +#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 |