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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
|
; Copyright (C) 2011-2023 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
|