|
|
1.1 ! root 1: ;; libgcc1 routines for the Hitachi h8/300 cpu. ! 2: ;; Contributed by Steve Chamberlain. ! 3: ;; [email protected] ! 4: ! 5: /* Copyright (C) 1994 Free Software Foundation, Inc. ! 6: ! 7: This file is free software; you can redistribute it and/or modify it ! 8: under the terms of the GNU General Public License as published by the ! 9: Free Software Foundation; either version 2, or (at your option) any ! 10: later version. ! 11: ! 12: In addition to the permissions in the GNU General Public License, the ! 13: Free Software Foundation gives you unlimited permission to link the ! 14: compiled version of this file with other programs, and to distribute ! 15: those programs without any restriction coming from the use of this ! 16: file. (The General Public License restrictions do apply in other ! 17: respects; for example, they cover modification of the file, and ! 18: distribution when not linked into another program.) ! 19: ! 20: This file is distributed in the hope that it will be useful, but ! 21: WITHOUT ANY WARRANTY; without even the implied warranty of ! 22: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! 23: General Public License for more details. ! 24: ! 25: You should have received a copy of the GNU General Public License ! 26: along with this program; see the file COPYING. If not, write to ! 27: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! 28: ! 29: /* As a special exception, if you link this library with other files, ! 30: some of which are compiled with GCC, to produce an executable, ! 31: this library does not by itself cause the resulting executable ! 32: to be covered by the GNU General Public License. ! 33: This exception does not however invalidate any other reasons why ! 34: the executable file might be covered by the GNU General Public License. */ ! 35: ! 36: /* Assembler register definitions. */ ! 37: ! 38: #define A0 r0 ! 39: #define A0L r0l ! 40: #define A0H r0h ! 41: ! 42: #define A1 r1 ! 43: #define A1L r1l ! 44: #define A1H r1h ! 45: ! 46: #define A2 r2 ! 47: #define A2L r2l ! 48: #define A2H r2h ! 49: ! 50: #define A3 r3 ! 51: #define A3L r3l ! 52: #define A3H r3h ! 53: ! 54: #define S0 r4 ! 55: #define S0L r4l ! 56: #define S0H r4h ! 57: ! 58: #define S1 r5 ! 59: #define S1L r5l ! 60: #define S1H r5h ! 61: ! 62: #define S2 r6 ! 63: #define S2L r6l ! 64: #define S2H r6h ! 65: ! 66: #ifdef __H8300__ ! 67: #define MOVP mov.w /* pointers are 16 bits */ ! 68: #define ADDP add.w ! 69: #define CMPP cmp.w ! 70: #define PUSHP push ! 71: #define POPP pop ! 72: ! 73: #define A0P r0 ! 74: #define A1P r1 ! 75: #define A2P r2 ! 76: #define A3P r3 ! 77: #define S0P r4 ! 78: #define S1P r5 ! 79: #define S2P r6 ! 80: #endif ! 81: ! 82: #ifdef __H8300H__ ! 83: #define MOVP mov.l /* pointers are 32 bits */ ! 84: #define ADDP add.l ! 85: #define CMPP cmp.l ! 86: #define PUSHP push.l ! 87: #define POPP pop.l ! 88: ! 89: #define A0P er0 ! 90: #define A1P er1 ! 91: #define A2P er2 ! 92: #define A3P er3 ! 93: #define S0P er4 ! 94: #define S1P er5 ! 95: #define S2P er6 ! 96: ! 97: #define A0E e0 ! 98: #define A1E e1 ! 99: #define A2E e2 ! 100: #define A3E e3 ! 101: #endif ! 102: ! 103: #ifdef L_cmpsi2 ! 104: #ifdef __H8300__ ! 105: .section .text ! 106: .align 2 ! 107: .global ___cmpsi2 ! 108: ___cmpsi2: ! 109: cmp.w A2,A0 ! 110: bne .L2 ! 111: cmp.w A3,A1 ! 112: bne .L2 ! 113: mov.w #1,A0 ! 114: rts ! 115: .L2: ! 116: cmp.w A0,A2 ! 117: bgt .L4 ! 118: bne .L3 ! 119: cmp.w A1,A3 ! 120: bls .L3 ! 121: .L4: ! 122: sub.w A0,A0 ! 123: rts ! 124: .L3: ! 125: mov.w #2,A0 ! 126: .L5: ! 127: rts ! 128: .end ! 129: #endif ! 130: #endif /* L_cmpsi2 */ ! 131: ! 132: #ifdef L_ucmpsi2 ! 133: #ifdef __H8300__ ! 134: .section .text ! 135: .align 2 ! 136: .global ___ucmpsi2 ! 137: ___ucmpsi2: ! 138: cmp.w A2,A0 ! 139: bne .L2 ! 140: cmp.w A3,A1 ! 141: bne .L2 ! 142: mov.w #1,A0 ! 143: rts ! 144: .L2: ! 145: cmp.w A0,A2 ! 146: bhi .L4 ! 147: bne .L3 ! 148: cmp.w A1,A3 ! 149: bls .L3 ! 150: .L4: ! 151: sub.w A0,A0 ! 152: rts ! 153: .L3: ! 154: mov.w #2,A0 ! 155: .L5: ! 156: rts ! 157: .end ! 158: #endif ! 159: #endif /* L_ucmpsi2 */ ! 160: ! 161: #ifdef L_divhi3 ! 162: ! 163: ;; HImode divides for the H8/300. ! 164: ;; We bunch all of this into one object file since there are several ! 165: ;; "supporting routines". ! 166: ! 167: ; general purpose normalize routine ! 168: ; ! 169: ; divisor in A0 ! 170: ; dividend in A1 ! 171: ; turns both into +ve numbers, and leaves what the answer sign ! 172: ; should be in A2L ! 173: ! 174: #ifdef __H8300__ ! 175: .section .text ! 176: .align 2 ! 177: divnorm: ! 178: mov.b #0x0,A2L ! 179: or A0H,A0H ; is divisor > 0 ! 180: bge _lab1 ! 181: not A0H ; no - then make it +ve ! 182: not A0L ! 183: adds #1,A0 ! 184: xor #0x1,A2L ; and remember that in A2L ! 185: _lab1: or A1H,A1H ; look at dividend ! 186: bge _lab2 ! 187: not A1H ; it is -ve, make it positive ! 188: not A1L ! 189: adds #1,A1 ! 190: xor #0x1,A2L; and toggle sign of result ! 191: _lab2: rts ! 192: ! 193: ; A0=A0/A1 signed ! 194: ! 195: .global ___divhi3 ! 196: ___divhi3: ! 197: bsr divnorm ! 198: bsr ___udivhi3 ! 199: negans: or A2L,A2L ; should answer be negative ? ! 200: beq _lab4 ! 201: not A0H ; yes, so make it so ! 202: not A0L ! 203: adds #1,A0 ! 204: _lab4: rts ! 205: ! 206: ; A0=A0%A1 signed ! 207: ! 208: .global ___modhi3 ! 209: ___modhi3: ! 210: bsr divnorm ! 211: bsr ___udivhi3 ! 212: mov A3,A0 ! 213: bra negans ! 214: ! 215: ; A0=A0%A1 unsigned ! 216: ! 217: .global ___umodhi3 ! 218: ___umodhi3: ! 219: bsr ___udivhi3 ! 220: mov A3,A0 ! 221: rts ! 222: ! 223: ; A0=A0/A1 unsigned ! 224: ; A3=A0%A1 unsigned ! 225: ; A2H trashed ! 226: ; D high 8 bits of denom ! 227: ; d low 8 bits of denom ! 228: ; N high 8 bits of num ! 229: ; n low 8 bits of num ! 230: ; M high 8 bits of mod ! 231: ; m low 8 bits of mod ! 232: ; Q high 8 bits of quot ! 233: ; q low 8 bits of quot ! 234: ; P preserve ! 235: ! 236: ; The h8 only has a 16/8 bit divide, so we look at the incoming and ! 237: ; see how to partition up the expression. ! 238: ! 239: .global ___udivhi3 ! 240: ___udivhi3: ! 241: ; A0 A1 A2 A3 ! 242: ; Nn Dd P ! 243: sub.w A3,A3 ; Nn Dd xP 00 ! 244: or A1H,A1H ! 245: bne divlongway ! 246: or A0H,A0H ! 247: beq _lab6 ! 248: ! 249: ; we know that D == 0 and N is != 0 ! 250: mov.b A0H,A3L ; Nn Dd xP 0N ! 251: divxu A1L,A3 ; MQ ! 252: mov.b A3L,A0H ; Q ! 253: ; dealt with N, do n ! 254: _lab6: mov.b A0L,A3L ; n ! 255: divxu A1L,A3 ; mq ! 256: mov.b A3L,A0L ; Qq ! 257: mov.b A3H,A3L ; m ! 258: mov.b #0x0,A3H ; Qq 0m ! 259: rts ! 260: ! 261: ; D != 0 - which means the denominator is ! 262: ; loop around to get the result. ! 263: ! 264: divlongway: ! 265: mov.b A0H,A3L ; Nn Dd xP 0N ! 266: mov.b #0x0,A0H ; high byte of answer has to be zero ! 267: mov.b #0x8,A2H ; 8 ! 268: div8: add.b A0L,A0L ; n*=2 ! 269: rotxl A3L ; Make remainder bigger ! 270: rotxl A3H ! 271: sub.w A1,A3 ; Q-=N ! 272: bhs setbit ; set a bit ? ! 273: add.w A1,A3 ; no : too far , Q+=N ! 274: ! 275: dec A2H ! 276: bne div8 ; next bit ! 277: rts ! 278: ! 279: setbit: inc A0L ; do insert bit ! 280: dec A2H ! 281: bne div8 ; next bit ! 282: rts ! 283: ! 284: #endif /* __H8300__ */ ! 285: #endif /* L_divhi3 */ ! 286: ! 287: #ifdef L_divsi3 ! 288: ! 289: ;; 4 byte integer divides for the H8/300. ! 290: ;; ! 291: ;; We have one routine which does all the work and lots of ! 292: ;; little ones which prepare the args and massage the sign. ! 293: ;; We bunch all of this into one object file since there are several ! 294: ;; "supporting routines". ! 295: ! 296: #ifdef __H8300H__ ! 297: .h8300h ! 298: #endif ! 299: ! 300: .section .text ! 301: .align 2 ! 302: ! 303: ; Put abs SIs into r0/r1 and r2/r3, and leave a 1 in r6l with sign of rest. ! 304: ; This function is here to keep branch displacements small. ! 305: ! 306: #ifdef __H8300__ ! 307: ! 308: divnorm: ! 309: mov.b #0,S2L ; keep the sign in S2 ! 310: mov.b A0H,A0H ; is the numerator -ve ! 311: bge postive ! 312: ! 313: ; negate arg ! 314: not A0H ! 315: not A1H ! 316: not A0L ! 317: not A1L ! 318: ! 319: add #1,A1L ! 320: addx #0,A1H ! 321: addx #0,A0H ! 322: addx #0,A0L ! 323: ! 324: mov.b #1,S2L ; the sign will be -ve ! 325: postive: ! 326: mov.b A2H,A2H ; is the denominator -ve ! 327: bge postive2 ! 328: not A2L ! 329: not A2H ! 330: not A3L ! 331: not A3H ! 332: add.b #1,A3L ! 333: addx #0,A3H ! 334: addx #0,A2L ! 335: addx #0,A2H ! 336: xor #1,S2L ; toggle result sign ! 337: postive2: ! 338: rts ! 339: ! 340: #else /* __H8300H__ */ ! 341: ! 342: divnorm: ! 343: mov.b #0,S2L ; keep the sign in S2 ! 344: mov.l A0P,A0P ; is the numerator -ve ! 345: bge postive ! 346: ! 347: neg.l A0P ; negate arg ! 348: mov.b #1,S2L ; the sign will be -ve ! 349: ! 350: postive: ! 351: mov.l A1P,A1P ; is the denominator -ve ! 352: bge postive2 ! 353: ! 354: neg.l A1P ; negate arg ! 355: xor.b #1,S2L ; toggle result sign ! 356: ! 357: postive2: ! 358: rts ! 359: ! 360: #endif ! 361: ! 362: ; numerator in A0/A1 ! 363: ; denominator in A2/A3 ! 364: .global ___modsi3 ! 365: ___modsi3: ! 366: PUSHP S2P ! 367: PUSHP S0P ! 368: PUSHP S1P ! 369: ! 370: bsr divnorm ! 371: bsr divmodsi4 ! 372: #ifdef __H8300__ ! 373: mov S0,A0 ! 374: mov S1,A1 ! 375: #else ! 376: mov.l S0P,A0P ! 377: #endif ! 378: bra exitdiv ! 379: ! 380: .global ___udivsi3 ! 381: ___udivsi3: ! 382: PUSHP S2P ! 383: PUSHP S0P ! 384: PUSHP S1P ! 385: mov.b #0,S2L ; keep sign low ! 386: bsr divmodsi4 ! 387: bra exitdiv ! 388: ! 389: .global ___umodsi3 ! 390: ___umodsi3: ! 391: PUSHP S2P ! 392: PUSHP S0P ! 393: PUSHP S1P ! 394: mov.b #0,S2L ; keep sign low ! 395: bsr divmodsi4 ! 396: #ifdef __H8300__ ! 397: mov S0,A0 ! 398: mov S1,A1 ! 399: #else ! 400: mov.l S0P,A0P ! 401: #endif ! 402: bra exitdiv ! 403: ! 404: .global ___divsi3 ! 405: ___divsi3: ! 406: PUSHP S2P ! 407: PUSHP S0P ! 408: PUSHP S1P ! 409: jsr divnorm ! 410: jsr divmodsi4 ! 411: ! 412: ; examine what the sign should be ! 413: exitdiv: ! 414: POPP S1P ! 415: POPP S0P ! 416: ! 417: or S2L,S2L ! 418: beq reti ! 419: ! 420: ; should be -ve ! 421: #ifdef __H8300__ ! 422: not A0H ! 423: not A1H ! 424: not A0L ! 425: not A1L ! 426: ! 427: add #1,A1L ! 428: addx #0,A1H ! 429: addx #0,A0H ! 430: addx #0,A0L ! 431: #else /* __H8300H__ */ ! 432: neg.l A0P ! 433: #endif ! 434: ! 435: reti: ! 436: POPP S2P ! 437: rts ! 438: ! 439: ; takes A0/A1 numerator (A0P for 300h) ! 440: ; A2/A3 denominator (A1P for 300h) ! 441: ; returns A0/A1 quotient (A0P for 300h) ! 442: ; S0/S1 remainder (S0P for 300h) ! 443: ; trashes S2 ! 444: ! 445: #ifdef __H8300__ ! 446: ! 447: divmodsi4: ! 448: sub.w S0,S0 ; zero play area ! 449: mov.w S0,S1 ! 450: mov.b A2H,S2H ! 451: or A2L,S2H ! 452: or A3H,S2H ! 453: bne DenHighZero ! 454: mov.b A0H,A0H ! 455: bne NumByte0Zero ! 456: mov.b A0L,A0L ! 457: bne NumByte1Zero ! 458: mov.b A1H,A1H ! 459: bne NumByte2Zero ! 460: bra NumByte3Zero ! 461: NumByte0Zero: ! 462: mov.b A0H,S1L ! 463: divxu A3L,S1 ! 464: mov.b S1L,A0H ! 465: NumByte1Zero: ! 466: mov.b A0L,S1L ! 467: divxu A3L,S1 ! 468: mov.b S1L,A0L ! 469: NumByte2Zero: ! 470: mov.b A1H,S1L ! 471: divxu A3L,S1 ! 472: mov.b S1L,A1H ! 473: NumByte3Zero: ! 474: mov.b A1L,S1L ! 475: divxu A3L,S1 ! 476: mov.b S1L,A1L ! 477: ! 478: mov.b S1H,S1L ! 479: mov.b #0x0,S1H ! 480: rts ! 481: ! 482: ; have to do the divide by shift and test ! 483: DenHighZero: ! 484: mov.b A0H,S1L ! 485: mov.b A0L,A0H ! 486: mov.b A1H,A0L ! 487: mov.b A1L,A1H ! 488: ! 489: mov.b #0,A1L ! 490: mov.b #24,S2H ; only do 24 iterations ! 491: ! 492: nextbit: ! 493: add.w A1,A1 ; double the answer guess ! 494: rotxl A0L ! 495: rotxl A0H ! 496: ! 497: rotxl S1L ; double remainder ! 498: rotxl S1H ! 499: rotxl S0L ! 500: rotxl S0H ! 501: sub.w A3,S1 ; does it all fit ! 502: subx A2L,S0L ! 503: subx A2H,S0H ! 504: bhs setone ! 505: ! 506: add.w A3,S1 ; no, restore mistake ! 507: addx A2L,S0L ! 508: addx A2H,S0H ! 509: ! 510: dec S2H ! 511: bne nextbit ! 512: rts ! 513: ! 514: setone: ! 515: inc A1L ! 516: dec S2H ! 517: bne nextbit ! 518: rts ! 519: ! 520: #else /* __H8300H__ */ ! 521: ! 522: divmodsi4: ! 523: sub.l S0P,S0P ; zero play area ! 524: mov.w A1E,A1E ; denominator top word 0? ! 525: bne DenHighZero ! 526: ! 527: ; do it the easy way, see page 107 in manual ! 528: mov.w A0E,A2 ! 529: extu.l A2P ! 530: divxu.w A1,A2P ! 531: mov.w A2E,A0E ! 532: divxu.w A1,A0P ! 533: mov.w A0E,S0 ! 534: mov.w A2,A0E ! 535: extu.l S0P ! 536: rts ! 537: ! 538: DenHighZero: ! 539: mov.w A0E,A2 ! 540: mov.b A2H,S0L ! 541: mov.b A2L,A2H ! 542: mov.b A0H,A2L ! 543: mov.w A2,A0E ! 544: mov.b A0L,A0H ! 545: mov.b #0,A0L ! 546: mov.b #24,S2H ; only do 24 iterations ! 547: ! 548: nextbit: ! 549: shll.l A0P ; double the answer guess ! 550: rotxl.l S0P ; double remainder ! 551: sub.l A1P,S0P ; does it all fit? ! 552: bhs setone ! 553: ! 554: add.l A1P,S0P ; no, restore mistake ! 555: dec S2H ! 556: bne nextbit ! 557: rts ! 558: ! 559: setone: ! 560: inc A0L ! 561: dec S2H ! 562: bne nextbit ! 563: rts ! 564: ! 565: #endif ! 566: #endif /* L_divsi3 */ ! 567: ! 568: #ifdef L_mulhi3 ! 569: ! 570: ;; HImode multiply. ! 571: ; The h8 only has an 8*8->16 multiply. ! 572: ; The answer is the same as: ! 573: ; ! 574: ; product = (srca.l * srcb.l) + ((srca.h * srcb.l) + (srcb.h * srca.l)) * 256 ! 575: ; (we can ignore A1.h * A0.h cause that will all off the top) ! 576: ; A0 in ! 577: ; A1 in ! 578: ; A0 answer ! 579: ! 580: #ifdef __H8300__ ! 581: .section .text ! 582: .align 2 ! 583: .global ___mulhi3 ! 584: ___mulhi3: ! 585: mov.b A1L,A2L ; A2l gets srcb.l ! 586: mulxu A0L,A2 ; A2 gets first sub product ! 587: ! 588: mov.b A0H,A3L ; prepare for ! 589: mulxu A1L,A3 ; second sub product ! 590: ! 591: add.b A3L,A2H ; sum first two terms ! 592: ! 593: mov.b A1H,A3L ; third sub product ! 594: mulxu A0L,A3 ! 595: ! 596: add.b A3L,A2H ; almost there ! 597: mov.w A2,A0 ; that is ! 598: rts ! 599: ! 600: #endif ! 601: #endif /* L_mulhi3 */ ! 602: ! 603: #ifdef L_mulsi3 ! 604: ! 605: ;; SImode multiply. ! 606: ;; ! 607: ;; I think that shift and add may be sufficient for this. Using the ! 608: ;; supplied 8x8->16 would need 10 ops of 14 cycles each + overhead. This way ! 609: ;; the inner loop uses maybe 20 cycles + overhead, but terminates ! 610: ;; quickly on small args. ! 611: ;; ! 612: ;; A0/A1 src_a ! 613: ;; A2/A3 src_b ! 614: ;; ! 615: ;; while (a) ! 616: ;; { ! 617: ;; if (a & 1) ! 618: ;; r += b; ! 619: ;; a >>= 1; ! 620: ;; b <<= 1; ! 621: ;; } ! 622: ! 623: .section .text ! 624: .align 2 ! 625: ! 626: #ifdef __H8300__ ! 627: ! 628: .global ___mulsi3 ! 629: ___mulsi3: ! 630: PUSHP S0P ! 631: PUSHP S1P ! 632: PUSHP S2P ! 633: ! 634: sub.w S0,S0 ! 635: sub.w S1,S1 ! 636: ! 637: ; while (a) ! 638: _top: mov.w A0,A0 ! 639: bne _more ! 640: mov.w A1,A1 ! 641: beq _done ! 642: _more: ; if (a & 1) ! 643: bld #0,A1L ! 644: bcc _nobit ! 645: ; r += b ! 646: add.w A3,S1 ! 647: addx A2L,S0L ! 648: addx A2H,S0H ! 649: _nobit: ! 650: ; a >>= 1 ! 651: shlr A0H ! 652: rotxr A0L ! 653: rotxr A1H ! 654: rotxr A1L ! 655: ! 656: ; b <<= 1 ! 657: add.w A3,A3 ! 658: addx A2L,A2L ! 659: addx A2H,A2H ! 660: bra _top ! 661: ! 662: _done: ! 663: mov.w S0,A0 ! 664: mov.w S1,A1 ! 665: POPP S2P ! 666: POPP S1P ! 667: POPP S0P ! 668: rts ! 669: ! 670: #else /* __H8300H__ */ ! 671: ! 672: .h8300h ! 673: ! 674: .global ___mulsi3 ! 675: ___mulsi3: ! 676: sub.l A2P,A2P ! 677: ! 678: ; while (a) ! 679: _top: mov.l A0P,A0P ! 680: beq _done ! 681: ! 682: ; if (a & 1) ! 683: bld #0,A0L ! 684: bcc _nobit ! 685: ! 686: ; r += b ! 687: add.l A1P,A2P ! 688: ! 689: _nobit: ! 690: ; a >>= 1 ! 691: shlr.l A0P ! 692: ! 693: ; b <<= 1 ! 694: shll.l A1P ! 695: bra _top ! 696: ! 697: _done: ! 698: mov.l A2P,A0P ! 699: rts ! 700: ! 701: #endif ! 702: #endif /* L_mulsi3 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.