summaryrefslogtreecommitdiff
path: root/libgcc/config/msp430/cmpsi2.S
blob: 6f076b68f6784ba5f02e1ed8df27a54b106bbd02 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
;   Copyright (C) 2012-2013 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/>.

#ifdef __MSP430X_LARGE__
#define ret_	RETA
#else
#define ret_	RET
#endif

	.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.

	;;  Note - this code is also used by the __ucmpsi2 routine below.

	.global	__cmpsi2
        .type   __cmpsi2, @function
__cmpsi2:
	;; A is in r12 (low), r13 (high)
	;; B is in r14 (low), r15 (high)
	;; Result put in r12

	cmp.w	r13, r15
	jeq	.L_compare_low
	jge	.L_less_than
.L_greater_than:
	mov.w	#2, r12
	ret_
.L_less_than:
	mov.w	#0, r12
	ret_

.L_compare_low:
	cmp.w	r12, r14
	jl	.L_greater_than
	jne     .L_less_than
	mov.w	#1, r12
	ret_

	.size	__cmpsi2, . - __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.

;;;  Note - this function branches into the __cmpsi2 code above.

	.global	__ucmpsi2
        .type   __ucmpsi2, @function
__ucmpsi2:
	;; A is in r12 (low), r13 (high)
	;; B is in r14 (low), r15 (high)
	;; Result put in r12

	tst	r13
	jn	.L_top_bit_set_in_A
	tst	r15
;;; If the top bit of B is set, but A's is clear we know that A < B.
	jn	.L_less_than
;;; Neither A nor B has their top bit set so we can use the __cmpsi2 routine.
;;; Note we use Jc rather than BR as that saves two bytes.  The TST insn always
;;; sets the C bit.
	jc	__cmpsi2

.L_top_bit_set_in_A:
	tst	r15
;;;  If both A and B have their top bit set we can use the __cmpsi2 routine.
	jn	__cmpsi2
;;; Otherwise A has its top bit set and B does not so A > B.
	jc	.L_greater_than

	.size	__ucmpsi2, . - __ucmpsi2