OLD | NEW |
| (Empty) |
1 // Inferno's libkern/vlrt-arm.c | |
2 // http://code.google.com/p/inferno-os/source/browse/libkern/vlrt-arm.c | |
3 // | |
4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. | |
5 // Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vita
nuova.com). All rights reserved. | |
6 // Portions Copyright 2009 The Go Authors. All rights reserved. | |
7 // | |
8 // Permission is hereby granted, free of charge, to any person obtaining a copy | |
9 // of this software and associated documentation files (the "Software"), to deal | |
10 // in the Software without restriction, including without limitation the rights | |
11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
12 // copies of the Software, and to permit persons to whom the Software is | |
13 // furnished to do so, subject to the following conditions: | |
14 // | |
15 // The above copyright notice and this permission notice shall be included in | |
16 // all copies or substantial portions of the Software. | |
17 // | |
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
23 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
24 // THE SOFTWARE. | |
25 | |
26 #include "../../cmd/ld/textflag.h" | |
27 | |
28 // declared here to avoid include of runtime.h | |
29 void runtime·panicstring(char*); | |
30 void runtime·panicdivide(void); | |
31 | |
32 typedef unsigned long ulong; | |
33 typedef unsigned int uint; | |
34 typedef unsigned short ushort; | |
35 typedef unsigned char uchar; | |
36 typedef signed char schar; | |
37 | |
38 #define SIGN(n) (1UL<<(n-1)) | |
39 | |
40 typedef struct Vlong Vlong; | |
41 struct Vlong | |
42 { | |
43 union | |
44 { | |
45 struct | |
46 { | |
47 ulong lo; | |
48 ulong hi; | |
49 }; | |
50 struct | |
51 { | |
52 ushort lols; | |
53 ushort loms; | |
54 ushort hils; | |
55 ushort hims; | |
56 }; | |
57 }; | |
58 }; | |
59 | |
60 void runtime·abort(void); | |
61 | |
62 #pragma textflag NOSPLIT | |
63 void | |
64 _addv(Vlong *r, Vlong a, Vlong b) | |
65 { | |
66 r->lo = a.lo + b.lo; | |
67 r->hi = a.hi + b.hi; | |
68 if(r->lo < a.lo) | |
69 r->hi++; | |
70 } | |
71 | |
72 #pragma textflag NOSPLIT | |
73 void | |
74 _subv(Vlong *r, Vlong a, Vlong b) | |
75 { | |
76 r->lo = a.lo - b.lo; | |
77 r->hi = a.hi - b.hi; | |
78 if(r->lo > a.lo) | |
79 r->hi--; | |
80 } | |
81 | |
82 void | |
83 _d2v(Vlong *y, double d) | |
84 { | |
85 union { double d; struct Vlong; } x; | |
86 ulong xhi, xlo, ylo, yhi; | |
87 int sh; | |
88 | |
89 x.d = d; | |
90 | |
91 xhi = (x.hi & 0xfffff) | 0x100000; | |
92 xlo = x.lo; | |
93 sh = 1075 - ((x.hi >> 20) & 0x7ff); | |
94 | |
95 ylo = 0; | |
96 yhi = 0; | |
97 if(sh >= 0) { | |
98 /* v = (hi||lo) >> sh */ | |
99 if(sh < 32) { | |
100 if(sh == 0) { | |
101 ylo = xlo; | |
102 yhi = xhi; | |
103 } else { | |
104 ylo = (xlo >> sh) | (xhi << (32-sh)); | |
105 yhi = xhi >> sh; | |
106 } | |
107 } else { | |
108 if(sh == 32) { | |
109 ylo = xhi; | |
110 } else | |
111 if(sh < 64) { | |
112 ylo = xhi >> (sh-32); | |
113 } | |
114 } | |
115 } else { | |
116 /* v = (hi||lo) << -sh */ | |
117 sh = -sh; | |
118 if(sh <= 11) { | |
119 ylo = xlo << sh; | |
120 yhi = (xhi << sh) | (xlo >> (32-sh)); | |
121 } else { | |
122 /* overflow */ | |
123 yhi = d; /* causes something awful */ | |
124 } | |
125 } | |
126 if(x.hi & SIGN(32)) { | |
127 if(ylo != 0) { | |
128 ylo = -ylo; | |
129 yhi = ~yhi; | |
130 } else | |
131 yhi = -yhi; | |
132 } | |
133 | |
134 y->hi = yhi; | |
135 y->lo = ylo; | |
136 } | |
137 | |
138 void | |
139 _f2v(Vlong *y, float f) | |
140 { | |
141 _d2v(y, f); | |
142 } | |
143 | |
144 void | |
145 runtime·float64toint64(double d, Vlong y) | |
146 { | |
147 _d2v(&y, d); | |
148 } | |
149 | |
150 void | |
151 runtime·float64touint64(double d, Vlong y) | |
152 { | |
153 _d2v(&y, d); | |
154 } | |
155 | |
156 double | |
157 _ul2d(ulong u) | |
158 { | |
159 // compensate for bug in c | |
160 if(u & SIGN(32)) { | |
161 u ^= SIGN(32); | |
162 return 2147483648. + u; | |
163 } | |
164 return u; | |
165 } | |
166 | |
167 double | |
168 _v2d(Vlong x) | |
169 { | |
170 if(x.hi & SIGN(32)) { | |
171 if(x.lo) { | |
172 x.lo = -x.lo; | |
173 x.hi = ~x.hi; | |
174 } else | |
175 x.hi = -x.hi; | |
176 return -(_ul2d(x.hi)*4294967296. + _ul2d(x.lo)); | |
177 } | |
178 return x.hi*4294967296. + _ul2d(x.lo); | |
179 } | |
180 | |
181 float | |
182 _v2f(Vlong x) | |
183 { | |
184 return _v2d(x); | |
185 } | |
186 | |
187 void | |
188 runtime·int64tofloat64(Vlong y, double d) | |
189 { | |
190 d = _v2d(y); | |
191 USED(&d); // FLUSH | |
192 } | |
193 | |
194 void | |
195 runtime·uint64tofloat64(Vlong y, double d) | |
196 { | |
197 d = _ul2d(y.hi)*4294967296. + _ul2d(y.lo); | |
198 USED(&d); // FLUSH | |
199 } | |
200 | |
201 static void | |
202 dodiv(Vlong num, Vlong den, Vlong *q, Vlong *r) | |
203 { | |
204 ulong numlo, numhi, denhi, denlo, quohi, quolo, t; | |
205 int i; | |
206 | |
207 numhi = num.hi; | |
208 numlo = num.lo; | |
209 denhi = den.hi; | |
210 denlo = den.lo; | |
211 | |
212 /* | |
213 * get a divide by zero | |
214 */ | |
215 if(denlo==0 && denhi==0) { | |
216 runtime·panicdivide(); | |
217 } | |
218 | |
219 /* | |
220 * set up the divisor and find the number of iterations needed | |
221 */ | |
222 if(numhi >= SIGN(32)) { | |
223 quohi = SIGN(32); | |
224 quolo = 0; | |
225 } else { | |
226 quohi = numhi; | |
227 quolo = numlo; | |
228 } | |
229 i = 0; | |
230 while(denhi < quohi || (denhi == quohi && denlo < quolo)) { | |
231 denhi = (denhi<<1) | (denlo>>31); | |
232 denlo <<= 1; | |
233 i++; | |
234 } | |
235 | |
236 quohi = 0; | |
237 quolo = 0; | |
238 for(; i >= 0; i--) { | |
239 quohi = (quohi<<1) | (quolo>>31); | |
240 quolo <<= 1; | |
241 if(numhi > denhi || (numhi == denhi && numlo >= denlo)) { | |
242 t = numlo; | |
243 numlo -= denlo; | |
244 if(numlo > t) | |
245 numhi--; | |
246 numhi -= denhi; | |
247 quolo |= 1; | |
248 } | |
249 denlo = (denlo>>1) | (denhi<<31); | |
250 denhi >>= 1; | |
251 } | |
252 | |
253 if(q) { | |
254 q->lo = quolo; | |
255 q->hi = quohi; | |
256 } | |
257 if(r) { | |
258 r->lo = numlo; | |
259 r->hi = numhi; | |
260 } | |
261 } | |
262 | |
263 void | |
264 _divvu(Vlong *q, Vlong n, Vlong d) | |
265 { | |
266 | |
267 if(n.hi == 0 && d.hi == 0) { | |
268 q->hi = 0; | |
269 q->lo = n.lo / d.lo; | |
270 return; | |
271 } | |
272 dodiv(n, d, q, 0); | |
273 } | |
274 | |
275 void | |
276 runtime·uint64div(Vlong n, Vlong d, Vlong q) | |
277 { | |
278 _divvu(&q, n, d); | |
279 } | |
280 | |
281 void | |
282 _modvu(Vlong *r, Vlong n, Vlong d) | |
283 { | |
284 | |
285 if(n.hi == 0 && d.hi == 0) { | |
286 r->hi = 0; | |
287 r->lo = n.lo % d.lo; | |
288 return; | |
289 } | |
290 dodiv(n, d, 0, r); | |
291 } | |
292 | |
293 void | |
294 runtime·uint64mod(Vlong n, Vlong d, Vlong q) | |
295 { | |
296 _modvu(&q, n, d); | |
297 } | |
298 | |
299 static void | |
300 vneg(Vlong *v) | |
301 { | |
302 | |
303 if(v->lo == 0) { | |
304 v->hi = -v->hi; | |
305 return; | |
306 } | |
307 v->lo = -v->lo; | |
308 v->hi = ~v->hi; | |
309 } | |
310 | |
311 void | |
312 _divv(Vlong *q, Vlong n, Vlong d) | |
313 { | |
314 long nneg, dneg; | |
315 | |
316 if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) { | |
317 if((long)n.lo == -0x80000000 && (long)d.lo == -1) { | |
318 // special case: 32-bit -0x80000000 / -1 causes wrong si
gn | |
319 q->lo = 0x80000000; | |
320 q->hi = 0; | |
321 return; | |
322 } | |
323 q->lo = (long)n.lo / (long)d.lo; | |
324 q->hi = ((long)q->lo) >> 31; | |
325 return; | |
326 } | |
327 nneg = n.hi >> 31; | |
328 if(nneg) | |
329 vneg(&n); | |
330 dneg = d.hi >> 31; | |
331 if(dneg) | |
332 vneg(&d); | |
333 dodiv(n, d, q, 0); | |
334 if(nneg != dneg) | |
335 vneg(q); | |
336 } | |
337 | |
338 void | |
339 runtime·int64div(Vlong n, Vlong d, Vlong q) | |
340 { | |
341 _divv(&q, n, d); | |
342 } | |
343 | |
344 void | |
345 _modv(Vlong *r, Vlong n, Vlong d) | |
346 { | |
347 long nneg, dneg; | |
348 | |
349 if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) { | |
350 r->lo = (long)n.lo % (long)d.lo; | |
351 r->hi = ((long)r->lo) >> 31; | |
352 return; | |
353 } | |
354 nneg = n.hi >> 31; | |
355 if(nneg) | |
356 vneg(&n); | |
357 dneg = d.hi >> 31; | |
358 if(dneg) | |
359 vneg(&d); | |
360 dodiv(n, d, 0, r); | |
361 if(nneg) | |
362 vneg(r); | |
363 } | |
364 | |
365 void | |
366 runtime·int64mod(Vlong n, Vlong d, Vlong q) | |
367 { | |
368 _modv(&q, n, d); | |
369 } | |
370 | |
371 void | |
372 _rshav(Vlong *r, Vlong a, int b) | |
373 { | |
374 long t; | |
375 | |
376 t = a.hi; | |
377 if(b >= 32) { | |
378 r->hi = t>>31; | |
379 if(b >= 64) { | |
380 /* this is illegal re C standard */ | |
381 r->lo = t>>31; | |
382 return; | |
383 } | |
384 r->lo = t >> (b-32); | |
385 return; | |
386 } | |
387 if(b <= 0) { | |
388 r->hi = t; | |
389 r->lo = a.lo; | |
390 return; | |
391 } | |
392 r->hi = t >> b; | |
393 r->lo = (t << (32-b)) | (a.lo >> b); | |
394 } | |
395 | |
396 void | |
397 _rshlv(Vlong *r, Vlong a, int b) | |
398 { | |
399 ulong t; | |
400 | |
401 t = a.hi; | |
402 if(b >= 32) { | |
403 r->hi = 0; | |
404 if(b >= 64) { | |
405 /* this is illegal re C standard */ | |
406 r->lo = 0; | |
407 return; | |
408 } | |
409 r->lo = t >> (b-32); | |
410 return; | |
411 } | |
412 if(b <= 0) { | |
413 r->hi = t; | |
414 r->lo = a.lo; | |
415 return; | |
416 } | |
417 r->hi = t >> b; | |
418 r->lo = (t << (32-b)) | (a.lo >> b); | |
419 } | |
420 | |
421 #pragma textflag NOSPLIT | |
422 void | |
423 _lshv(Vlong *r, Vlong a, int b) | |
424 { | |
425 if(b >= 32) { | |
426 r->lo = 0; | |
427 if(b >= 64) { | |
428 /* this is illegal re C standard */ | |
429 r->hi = 0; | |
430 return; | |
431 } | |
432 r->hi = a.lo << (b-32); | |
433 return; | |
434 } | |
435 if(b <= 0) { | |
436 r->lo = a.lo; | |
437 r->hi = a.hi; | |
438 return; | |
439 } | |
440 r->lo = a.lo << b; | |
441 r->hi = (a.lo >> (32-b)) | (a.hi << b); | |
442 } | |
443 | |
444 void | |
445 _andv(Vlong *r, Vlong a, Vlong b) | |
446 { | |
447 r->hi = a.hi & b.hi; | |
448 r->lo = a.lo & b.lo; | |
449 } | |
450 | |
451 void | |
452 _orv(Vlong *r, Vlong a, Vlong b) | |
453 { | |
454 r->hi = a.hi | b.hi; | |
455 r->lo = a.lo | b.lo; | |
456 } | |
457 | |
458 void | |
459 _xorv(Vlong *r, Vlong a, Vlong b) | |
460 { | |
461 r->hi = a.hi ^ b.hi; | |
462 r->lo = a.lo ^ b.lo; | |
463 } | |
464 | |
465 void | |
466 _vpp(Vlong *l, Vlong *r) | |
467 { | |
468 | |
469 l->hi = r->hi; | |
470 l->lo = r->lo; | |
471 r->lo++; | |
472 if(r->lo == 0) | |
473 r->hi++; | |
474 } | |
475 | |
476 void | |
477 _vmm(Vlong *l, Vlong *r) | |
478 { | |
479 | |
480 l->hi = r->hi; | |
481 l->lo = r->lo; | |
482 if(r->lo == 0) | |
483 r->hi--; | |
484 r->lo--; | |
485 } | |
486 | |
487 void | |
488 _ppv(Vlong *l, Vlong *r) | |
489 { | |
490 | |
491 r->lo++; | |
492 if(r->lo == 0) | |
493 r->hi++; | |
494 l->hi = r->hi; | |
495 l->lo = r->lo; | |
496 } | |
497 | |
498 void | |
499 _mmv(Vlong *l, Vlong *r) | |
500 { | |
501 | |
502 if(r->lo == 0) | |
503 r->hi--; | |
504 r->lo--; | |
505 l->hi = r->hi; | |
506 l->lo = r->lo; | |
507 } | |
508 | |
509 #pragma textflag NOSPLIT | |
510 void | |
511 _vasop(Vlong *ret, void *lv, void fn(Vlong*, Vlong, Vlong), int type, Vlong rv) | |
512 { | |
513 Vlong t, u; | |
514 | |
515 u = *ret; | |
516 switch(type) { | |
517 default: | |
518 runtime·abort(); | |
519 break; | |
520 | |
521 case 1: /* schar */ | |
522 t.lo = *(schar*)lv; | |
523 t.hi = t.lo >> 31; | |
524 fn(&u, t, rv); | |
525 *(schar*)lv = u.lo; | |
526 break; | |
527 | |
528 case 2: /* uchar */ | |
529 t.lo = *(uchar*)lv; | |
530 t.hi = 0; | |
531 fn(&u, t, rv); | |
532 *(uchar*)lv = u.lo; | |
533 break; | |
534 | |
535 case 3: /* short */ | |
536 t.lo = *(short*)lv; | |
537 t.hi = t.lo >> 31; | |
538 fn(&u, t, rv); | |
539 *(short*)lv = u.lo; | |
540 break; | |
541 | |
542 case 4: /* ushort */ | |
543 t.lo = *(ushort*)lv; | |
544 t.hi = 0; | |
545 fn(&u, t, rv); | |
546 *(ushort*)lv = u.lo; | |
547 break; | |
548 | |
549 case 9: /* int */ | |
550 t.lo = *(int*)lv; | |
551 t.hi = t.lo >> 31; | |
552 fn(&u, t, rv); | |
553 *(int*)lv = u.lo; | |
554 break; | |
555 | |
556 case 10: /* uint */ | |
557 t.lo = *(uint*)lv; | |
558 t.hi = 0; | |
559 fn(&u, t, rv); | |
560 *(uint*)lv = u.lo; | |
561 break; | |
562 | |
563 case 5: /* long */ | |
564 t.lo = *(long*)lv; | |
565 t.hi = t.lo >> 31; | |
566 fn(&u, t, rv); | |
567 *(long*)lv = u.lo; | |
568 break; | |
569 | |
570 case 6: /* ulong */ | |
571 t.lo = *(ulong*)lv; | |
572 t.hi = 0; | |
573 fn(&u, t, rv); | |
574 *(ulong*)lv = u.lo; | |
575 break; | |
576 | |
577 case 7: /* vlong */ | |
578 case 8: /* uvlong */ | |
579 fn(&u, *(Vlong*)lv, rv); | |
580 *(Vlong*)lv = u; | |
581 break; | |
582 } | |
583 *ret = u; | |
584 } | |
585 | |
586 void | |
587 _p2v(Vlong *ret, void *p) | |
588 { | |
589 long t; | |
590 | |
591 t = (ulong)p; | |
592 ret->lo = t; | |
593 ret->hi = 0; | |
594 } | |
595 | |
596 void | |
597 _sl2v(Vlong *ret, long sl) | |
598 { | |
599 long t; | |
600 | |
601 t = sl; | |
602 ret->lo = t; | |
603 ret->hi = t >> 31; | |
604 } | |
605 | |
606 void | |
607 _ul2v(Vlong *ret, ulong ul) | |
608 { | |
609 long t; | |
610 | |
611 t = ul; | |
612 ret->lo = t; | |
613 ret->hi = 0; | |
614 } | |
615 | |
616 #pragma textflag NOSPLIT | |
617 void | |
618 _si2v(Vlong *ret, int si) | |
619 { | |
620 ret->lo = (long)si; | |
621 ret->hi = (long)si >> 31; | |
622 } | |
623 | |
624 void | |
625 _ui2v(Vlong *ret, uint ui) | |
626 { | |
627 long t; | |
628 | |
629 t = ui; | |
630 ret->lo = t; | |
631 ret->hi = 0; | |
632 } | |
633 | |
634 void | |
635 _sh2v(Vlong *ret, long sh) | |
636 { | |
637 long t; | |
638 | |
639 t = (sh << 16) >> 16; | |
640 ret->lo = t; | |
641 ret->hi = t >> 31; | |
642 } | |
643 | |
644 void | |
645 _uh2v(Vlong *ret, ulong ul) | |
646 { | |
647 long t; | |
648 | |
649 t = ul & 0xffff; | |
650 ret->lo = t; | |
651 ret->hi = 0; | |
652 } | |
653 | |
654 void | |
655 _sc2v(Vlong *ret, long uc) | |
656 { | |
657 long t; | |
658 | |
659 t = (uc << 24) >> 24; | |
660 ret->lo = t; | |
661 ret->hi = t >> 31; | |
662 } | |
663 | |
664 void | |
665 _uc2v(Vlong *ret, ulong ul) | |
666 { | |
667 long t; | |
668 | |
669 t = ul & 0xff; | |
670 ret->lo = t; | |
671 ret->hi = 0; | |
672 } | |
673 | |
674 long | |
675 _v2sc(Vlong rv) | |
676 { | |
677 long t; | |
678 | |
679 t = rv.lo & 0xff; | |
680 return (t << 24) >> 24; | |
681 } | |
682 | |
683 long | |
684 _v2uc(Vlong rv) | |
685 { | |
686 | |
687 return rv.lo & 0xff; | |
688 } | |
689 | |
690 long | |
691 _v2sh(Vlong rv) | |
692 { | |
693 long t; | |
694 | |
695 t = rv.lo & 0xffff; | |
696 return (t << 16) >> 16; | |
697 } | |
698 | |
699 long | |
700 _v2uh(Vlong rv) | |
701 { | |
702 | |
703 return rv.lo & 0xffff; | |
704 } | |
705 | |
706 long | |
707 _v2sl(Vlong rv) | |
708 { | |
709 | |
710 return rv.lo; | |
711 } | |
712 | |
713 long | |
714 _v2ul(Vlong rv) | |
715 { | |
716 | |
717 return rv.lo; | |
718 } | |
719 | |
720 #pragma textflag NOSPLIT | |
721 long | |
722 _v2si(Vlong rv) | |
723 { | |
724 | |
725 return rv.lo; | |
726 } | |
727 | |
728 long | |
729 _v2ui(Vlong rv) | |
730 { | |
731 | |
732 return rv.lo; | |
733 } | |
734 | |
735 int | |
736 _testv(Vlong rv) | |
737 { | |
738 return rv.lo || rv.hi; | |
739 } | |
740 | |
741 int | |
742 _eqv(Vlong lv, Vlong rv) | |
743 { | |
744 return lv.lo == rv.lo && lv.hi == rv.hi; | |
745 } | |
746 | |
747 int | |
748 _nev(Vlong lv, Vlong rv) | |
749 { | |
750 return lv.lo != rv.lo || lv.hi != rv.hi; | |
751 } | |
752 | |
753 int | |
754 _ltv(Vlong lv, Vlong rv) | |
755 { | |
756 return (long)lv.hi < (long)rv.hi || | |
757 (lv.hi == rv.hi && lv.lo < rv.lo); | |
758 } | |
759 | |
760 int | |
761 _lev(Vlong lv, Vlong rv) | |
762 { | |
763 return (long)lv.hi < (long)rv.hi || | |
764 (lv.hi == rv.hi && lv.lo <= rv.lo); | |
765 } | |
766 | |
767 int | |
768 _gtv(Vlong lv, Vlong rv) | |
769 { | |
770 return (long)lv.hi > (long)rv.hi || | |
771 (lv.hi == rv.hi && lv.lo > rv.lo); | |
772 } | |
773 | |
774 #pragma textflag NOSPLIT | |
775 int | |
776 _gev(Vlong lv, Vlong rv) | |
777 { | |
778 return (long)lv.hi > (long)rv.hi || | |
779 (lv.hi == rv.hi && lv.lo >= rv.lo); | |
780 } | |
781 | |
782 int | |
783 _lov(Vlong lv, Vlong rv) | |
784 { | |
785 return lv.hi < rv.hi || | |
786 (lv.hi == rv.hi && lv.lo < rv.lo); | |
787 } | |
788 | |
789 int | |
790 _lsv(Vlong lv, Vlong rv) | |
791 { | |
792 return lv.hi < rv.hi || | |
793 (lv.hi == rv.hi && lv.lo <= rv.lo); | |
794 } | |
795 | |
796 int | |
797 _hiv(Vlong lv, Vlong rv) | |
798 { | |
799 return lv.hi > rv.hi || | |
800 (lv.hi == rv.hi && lv.lo > rv.lo); | |
801 } | |
802 | |
803 int | |
804 _hsv(Vlong lv, Vlong rv) | |
805 { | |
806 return lv.hi > rv.hi || | |
807 (lv.hi == rv.hi && lv.lo >= rv.lo); | |
808 } | |
OLD | NEW |