1: /* 2: * @(#)emulate.s 7.1 (Berkeley) 6/5/86 3: */ 4: 5: #ifdef VAX630 6: /* 7: * String instruction emulation - MicroVAX only. These routines are called 8: * from locore.s when an "emulate" fault occurs on the MicroVAX. They are 9: * called with the stack set up as follows: 10: * 11: * (sp): Return address of trap handler 12: * 4(sp): Instruction Opcode (also holds PSL result from emulator) 13: * 8(sp): Instruction PC 14: * 12(sp): Operand 1 15: * 16(sp): Operand 2 16: * 20(sp): Operand 3 17: * 24(sp): Operand 4 18: * 28(sp): Operand 5 19: * 32(sp): Operand 6 20: * 36(sp): old Register 11 21: * 40(sp): old Register 10 22: * 44(sp): Return PC 23: * 48(sp): Return PSL 24: * 52(sp): TOS before instruction 25: * 26: * R11 and r10 are available for use. If any routine needs to use r9-r1 27: * they need to save them first (unless those registers are SUPPOSED to be 28: * messed with by the "instruction"). These routines leave their results 29: * in registers 0-5 explicitly, as needed, and use the macros defined below 30: * to link up with calling routine. 31: */ 32: 33: #define return rsb 34: #define savepsl movpsl 4(sp) 35: #define setpsl(reg) movl reg,4(sp) 36: #define overflowpsl movl $2,4(sp) 37: #define arg1 12(sp) 38: #define arg2 16(sp) 39: #define arg3 20(sp) 40: #define arg4 24(sp) 41: #define arg5 28(sp) 42: #define arg6 32(sp) 43: #define argub(num,reg) movzbl 8+4*num(sp),reg 44: #define arguw(num,reg) movzwl 8+4*num(sp),reg 45: #define argul(num,reg) movl 8+4*num(sp),reg 46: #define argb(num,reg) cvtbl 8+4*num(sp),reg 47: #define argw(num,reg) cvtwl 8+4*num(sp),reg 48: #define argl(num,reg) movl 8+4*num(sp),reg 49: #define toarg(reg,num) movl reg,8+4*num(sp) 50: 51: 52: .text 53: .align 1 54: .globl _EMcrc 55: _EMcrc: 56: argl(1,r11) # (1) table address == r11 57: argl(2,r0) # (2) initial crc == r0 58: toarg(r8,1) # save r8 in arg1 spot 59: argl(4,r8) # (4) source address == r8 60: toarg(r1,4) # save r1 in arg4 spot 61: tstl arg3 # (3) source length == "arg3" 62: jeql Lcrc_out 63: Lcrc_loop: 64: xorb2 (r8)+,r0 65: extzv $0,$4,r0,r10 66: extzv $4,$28,r0,r1 67: xorl3 r1,(r11)[r10],r0 68: extzv $0,$4,r0,r10 69: extzv $4,$28,r0,r1 70: xorl3 r1,(r11)[r10],r0 71: decl arg3 72: jneq Lcrc_loop 73: tstl r0 74: Lcrc_out: 75: savepsl 76: argl(1,r8) 77: argl(4,r1) 78: return 79: 80: 81: .align 1 82: .globl _EMmovtc 83: _EMmovtc: 84: arguw(1,r0) # (1) source length == r0 85: argl(2,r1) # (2) source address == r1 86: argub(3,r11) # (3) fill character == r11 87: argl(4,r3) # (4) table address == r3 88: argl(6,r5) # (6) destination address == r5 89: arguw(5,r4) # (5) destination length == r4 90: jeql Lmovtc_out 91: Lmovtc_loop: 92: tstl r0 93: jeql Lmovtc_2loop 94: movzbl (r1)+,r2 95: movb (r3)[r2],(r5)+ 96: decl r0 97: decl r4 98: jeql Lmovtc_out 99: jbr Lmovtc_loop 100: Lmovtc_2loop: 101: movb r11,(r5)+ 102: decl r4 103: jneq Lmovtc_2loop 104: Lmovtc_out: 105: cmpl r4,r0 106: savepsl 107: clrl r2 108: return 109: 110: 111: .align 1 112: .globl _EMmovtuc 113: _EMmovtuc: 114: arguw(1,r0) # (1) source length == r0 115: argl(2,r1) # (2) source address == r1 116: argub(3,r11) # (3) escape character == r11 117: argl(4,r3) # (4) table address == r3 118: argl(6,r5) # (6) destination address == r5 119: arguw(5,r4) # (5) destination length == r4 120: jeql Lmovtuc_out 121: Lmovtuc_loop: 122: tstl r0 123: jeql Lmovtuc_out 124: movzbl (r1),r2 125: movzbl (r3)[r2],r2 126: cmpl r2,r11 127: jeql Lmovtuc_out 128: movzbl (r1)+,r2 129: movb (r3)[r2],(r5)+ 130: decl r0 131: decl r4 132: jneq Lmovtuc_loop 133: Lmovtuc_out: 134: cmpl r4,r0 135: savepsl 136: clrl r2 137: return 138: 139: 140: .align 1 141: .globl _EMmatchc 142: _EMmatchc: 143: argl(2,r10) # (2) substring address == r10 144: arguw(3,r2) # (3) source length == r2 145: argl(4,r3) # (4) source address == r3 146: arguw(1,r11) # (1) substring length == r11 147: jeql Lmatchc_out # temp source address == r1 148: addl2 r10,r11 # temp substring address == r0 149: tstl r2 150: jeql Lmatchc_out 151: Lmatchc_loop: 152: cmpb (r10),(r3) 153: jneq Lmatchc_fail 154: movl r3,r1 155: movl r10,r0 156: Lmatchc_2loop: 157: cmpl r0,r11 158: jeql Lmatchc_succ 159: cmpb (r0)+,(r1)+ 160: jeql Lmatchc_2loop 161: Lmatchc_fail: 162: incl r3 163: decl r2 164: jneq Lmatchc_loop 165: movl r10,r1 166: subl3 r10,r11,r0 167: jbr Lmatchc_out 168: Lmatchc_succ: 169: movl r11,r1 170: clrl r0 171: Lmatchc_out: 172: savepsl 173: return 174: 175: 176: .align 1 177: .globl _EMspanc 178: _EMspanc: 179: argl(2,r1) # (2) string address == r1 180: argl(3,r3) # (3) table address == r3 181: argub(4,r2) # (4) character-mask == r2 182: arguw(1,r0) # (1) string length == r0 183: jeql Lspanc_out 184: Lspanc_loop: 185: movzbl (r1),r11 186: mcomb (r3)[r11],r11 187: bicb3 r11,r2,r11 188: jeql Lspanc_out 189: incl r1 190: decl r0 191: jneq Lspanc_loop 192: Lspanc_out: 193: savepsl 194: clrl r2 195: return 196: 197: 198: .align 1 199: .globl _EMscanc 200: _EMscanc: 201: argl(2,r1) # (2) string address == r1 202: argl(3,r3) # (3) table address == r3 203: argub(4,r2) # (4) character-mask == r2 204: arguw(1,r0) # (1) string length == r0 205: jeql Lscanc_out 206: Lscanc_loop: 207: movzbl (r1),r11 208: mcomb (r3)[r11],r11 209: bicb3 r11,r2,r11 210: jneq Lscanc_out 211: incl r1 212: decl r0 213: jneq Lscanc_loop 214: Lscanc_out: 215: savepsl 216: clrl r2 217: return 218: 219: 220: .align 1 221: .globl _EMskpc 222: _EMskpc: 223: argub(1,r11) # (1) character == r11 224: argl(3,r1) # (3) string address == r1 225: arguw(2,r0) # (2) string length == r0 226: incl r0 227: Lskpc_loop: 228: decl r0 229: jeql Lskpc_out 230: cmpb (r1)+,r11 231: jeql Lskpc_loop 232: decl r1 233: tstl r0 234: Lskpc_out: 235: savepsl 236: return 237: 238: 239: .align 1 240: .globl _EMlocc 241: _EMlocc: 242: argub(1,r11) # (1) character == r11 243: argl(3,r1) # (3) string address == r1 244: arguw(2,r0) # (2) string length == r0 245: incl r0 246: Llocc_loop: 247: decl r0 248: jeql Llocc_out 249: cmpb (r1)+,r11 250: jneq Llocc_loop 251: decl r1 252: tstl r0 253: Llocc_out: 254: savepsl 255: return 256: 257: 258: .align 1 259: .globl _EMcmpc3 260: _EMcmpc3: 261: argl(2,r1) # (2) string1 address == r1 262: argl(3,r3) # (3) string2 address == r3 263: arguw(1,r0) # (1) strings' length == r0 264: jeql Lcmpc3_out 265: Lcmpc3_loop: 266: cmpb (r1),(r3) 267: jneq Lcmpc3_out 268: incl r1 269: incl r3 270: decl r0 271: jneq Lcmpc3_loop 272: Lcmpc3_out: 273: savepsl 274: movl r0,r2 275: return 276: 277: 278: .align 1 279: .globl _EMcmpc5 280: _EMcmpc5: 281: argl(2,r1) # (2) string1 address == r1 282: argub(3,r11) # (1) fill character == r11 283: arguw(4,r2) # (1) string2 length == r2 284: argl(5,r3) # (3) string2 address == r3 285: arguw(1,r0) # (1) string1 length == r0 286: jeql Lcmpc5_str2 287: Lcmpc5_loop: 288: tstl r2 289: jeql Lcmpc5_str1loop 290: cmpb (r1),(r3) 291: jneq Lcmpc5_out 292: incl r1 293: incl r3 294: decl r2 295: decl r0 296: jneq Lcmpc5_loop 297: Lcmpc5_str2: 298: tstl r2 299: jeql Lcmpc5_out 300: Lcmpc5_str2loop: 301: cmpb r11,(r3) 302: jneq Lcmpc5_out 303: incl r3 304: decl r2 305: jneq Lcmpc5_str2loop 306: jbr Lcmpc5_out 307: Lcmpc5_str1loop: 308: cmpb (r1),r11 309: jneq Lcmpc5_out 310: incl r1 311: decl r0 312: jneq Lcmpc5_str1loop 313: Lcmpc5_out: 314: savepsl 315: return 316: 317: 318: /* 319: * Packed Decimal string operations 320: */ 321: 322: #define POSITIVE $12 323: #define NEGATIVE $13 324: #define NEGATIVEalt $11 325: 326: 327: .align 1 328: .globl _EMaddp4 329: _EMaddp4: 330: toarg(r9,6) # save register r9 in arg6 spot 331: arguw(1,r11) # (1) source length == r11 332: argl(2,r10) # (2) source address == r10 333: arguw(3,r9) # (3) destination length == r9 334: argl(4,r3) # (4) destination address == r3 335: # arg4 will be needed later 336: # arg5 holds destination address of LSNibble temporarily 337: ashl $-1,r11,r11 338: addl2 r11,r10 # source address of LSNibble 339: incl r11 # source length is in bytes 340: ashl $-1,r9,r9 341: addl2 r9,r3 # r3 = destination address of LSNibble 342: incl r9 # destination length is in bytes 343: toarg(r3,5) # stored in arg5 spot 344: extzv $0,$4,(r3),r2 # set standard +/- indicators in destination 345: cmpl r2,NEGATIVE 346: jeql L112 347: cmpl r2,NEGATIVEalt 348: jeql L111 349: insv POSITIVE,$0,$4,(r3) 350: jbr L112 351: L111: 352: insv NEGATIVE,$0,$4,(r3) 353: L112: 354: extzv $0,$4,(r10),r2 # r2 = standard +/- of source 355: cmpl r2,NEGATIVE 356: jeql L114 357: cmpl r2,NEGATIVEalt 358: jeql L113 359: movl POSITIVE,r2 360: jbr L114 361: L113: 362: movl NEGATIVE,r2 363: L114: 364: cmpl r11,r9 # if source is longer than destination 365: jleq L115 366: movl r9,r11 # set source length == destination length 367: L115: 368: extzv $4,$4,(r3),r9 # r9 = LSDigit of destination 369: extzv $4,$4,(r10),r1 # r1 = LSDigit of source 370: extzv $0,$4,(r3),r0 371: cmpl r0,r2 # if signs of operands are not equal 372: jeql Laddp4_same # do a subtraction 373: clrl r2 # r2 is non-zero if result is non-zero 374: subl2 r1,r9 # r9 = "addition" of operands' high nibble 375: jbr L119 # jump into addition loop 376: Laddp4_diff_loop: 377: decl r3 378: extzv $0,$4,(r3),r0 379: addl2 r0,r1 # r1 = carry + next (low) nibble of source 380: decl r10 381: extzv $0,$4,(r10),r0 382: subl2 r0,r1 # r1 -= next (low) nibble of destination 383: jgeq L121 # if negative result 384: mnegl $1,r9 # r9 == carry = -1 385: addl2 $10,r1 # r1 == result += 10 386: jbr L122 # else 387: L121: 388: clrl r9 # r9 == carry = 0 389: L122: 390: insv r1,$0,$4,(r3) # store result low nibble 391: bisl2 r1,r2 392: extzv $4,$4,(r3),r0 393: addl2 r0,r9 # r9 = carry + next (high) nibble of source 394: extzv $4,$4,(r10),r0 395: subl2 r0,r9 # r9 -= next (high) nibble of destination 396: L119: 397: jgeq L117 # if negative result 398: mnegl $1,r1 # r1 == carry = -1 399: addl2 $10,r9 # r9 == result += 10 400: jbr L118 # else 401: L117: 402: clrl r1 # r1 == carry = 0 403: L118: 404: insv r9,$4,$4,(r3) # store result high nibble 405: bisl2 r9,r2 # r2 is non-zero if result is non-zero 406: decl r11 # while (--source length) 407: jneq Laddp4_diff_loop 408: argl(4,r10) # r10 = address of destination MSNibble 409: jbr Laddp4_diff_carry 410: Laddp4_diff_carlop: 411: decl r3 412: extzv $0,$4,(r3),r0 413: addl2 r0,r1 # r1 == carry += next (low) nibble 414: jgeq L127 # if less than zero 415: movl r1,r9 # r9 == carry (must be -1) 416: movl $9,r1 # r1 == result = 9 417: jbr L128 418: L127: # else 419: clrl r9 # r9 == carry = 0 420: L128: 421: insv r1,$0,$4,(r3) # store result 422: bisl2 r1,r2 423: extzv $4,$4,(r3),r0 424: addl2 r0,r9 # r9 == carry += next (high) nibble 425: jgeq L129 # if less than zero 426: movl r9,r1 # r1 == carry (must be -1) 427: movl $9,r9 # r9 == result = 9 428: jbr L130 429: L129: 430: clrl r1 431: L130: 432: insv r9,$4,$4,(r3) # store result 433: bisl2 r9,r2 434: Laddp4_diff_carry: 435: cmpl r3,r10 436: jneq Laddp4_diff_carlop 437: tstl r1 # if carry out of MSN then fix up result 438: jeql Laddp4_add_done 439: argl(5,r3) # r3 == address of LSN of destination 440: extzv $0,$4,(r3),r0 441: cmpl r0,NEGATIVE # switch sign of result 442: jneq L132 443: insv POSITIVE,$0,$4,(r3) 444: jbr L133 445: L132: 446: insv NEGATIVE,$0,$4,(r3) 447: L133: 448: extzv $4,$4,(r3),r0 # normalize result (carry out of MSN into LSN) 449: subl3 r0,$10,r9 # r9 = 10 - destination LSNibble 450: jbr L134 451: L137: 452: movl $9,r1 453: Laddp4_diff_norm: 454: insv r9,$4,$4,(r3) 455: cmpl r3,r10 # while (not at MSNibble) 456: jeql Laddp4_add_done 457: decl r3 458: extzv $0,$4,(r3),r0 # low nibble = (9 + carry) - low nibble 459: subl2 r0,r1 460: cmpl r1,$9 461: jleq L135 462: clrl r1 463: movl $10,r9 464: jbr L136 465: L135: 466: movl $9,r9 467: L136: 468: insv r1,$0,$4,(r3) 469: extzv $4,$4,(r3),r0 # high nibble = (9 + carry) - high nibble 470: subl2 r0,r9 471: L134: 472: cmpl r9,$9 473: jleq L137 474: clrl r9 475: movl $10,r1 476: jbr Laddp4_diff_norm 477: 478: Laddp4_same: # operands are of the same sign 479: clrl r2 480: addl2 r1,r9 481: jbr L139 482: Laddp4_same_loop: 483: decl r3 484: extzv $0,$4,(r3),r0 485: addl2 r0,r1 # r1 == carry += next (low) nibble of dest 486: decl r10 487: extzv $0,$4,(r10),r0 488: addl2 r0,r1 # r1 += next (low) nibble of source 489: cmpl r1,$9 # if result > 9 490: jleq L141 491: movl $1,r9 # r9 == carry = 1 492: subl2 $10,r1 # r1 == result -= 10 493: jbr L142 494: L141: # else 495: clrl r9 # r9 == carry = 0 496: L142: 497: insv r1,$0,$4,(r3) # store result 498: bisl2 r1,r2 499: extzv $4,$4,(r10),r0 500: addl2 r0,r9 # ditto for high nibble 501: extzv $4,$4,(r3),r0 502: addl2 r0,r9 503: L139: 504: cmpl r9,$9 505: jleq L143 506: movl $1,r1 507: subl2 $10,r9 508: jbr L144 509: L143: 510: clrl r1 511: L144: 512: insv r9,$4,$4,(r3) 513: bisl2 r9,r2 514: decl r11 # while (--source length) 515: jneq Laddp4_same_loop 516: argl(4,r10) # r10 = destination address of MSNibble 517: jbr Laddp4_same_carry 518: Laddp4_same_cloop: 519: decl r3 520: extzv $0,$4,(r3),r0 # propagate carry up to MSNibble of destination 521: addl2 r0,r1 522: cmpl r1,$10 523: jneq L147 524: movl $1,r9 525: clrl r1 526: jbr L148 527: L147: 528: clrl r9 529: L148: 530: insv r1,$0,$4,(r3) 531: bisl2 r1,r2 532: extzv $4,$4,(r3),r0 533: addl2 r0,r9 534: cmpl r9,$10 535: jneq L149 536: movl $1,r1 537: clrl r9 538: jbr L150 539: L149: 540: clrl r1 541: L150: 542: insv r9,$4,$4,(r3) 543: bisl2 r9,r2 544: Laddp4_same_carry: 545: cmpl r3,r10 546: jneq Laddp4_same_cloop 547: 548: Laddp4_add_done: 549: argl(5,r3) # r3 = destination address of LSNibble 550: tstl r2 # if zero result 551: jneq L151 552: savepsl # remember that for condition codes 553: insv POSITIVE,$0,$4,(r3) # make sure sign of result is positive 554: jbr Laddp4_out 555: L151: # else 556: extzv $0,$4,(r3),r0 557: cmpl r0,NEGATIVE # if result is negative 558: jneq Laddp4_out 559: mnegl r2,r2 # remember THAT in Cond Codes 560: savepsl 561: Laddp4_out: 562: argl(4,r3) 563: argl(2,r1) 564: clrl r0 565: clrl r2 566: argl(6,r9) # restore r9 from stack 567: return 568: 569: 570: .align 1 571: .globl _EMmovp 572: _EMmovp: 573: arguw(1,r11) # (1) string length == r11 574: argl(2,r10) # (1) source address == r10 575: argl(3,r3) # (1) destination address == r3 576: # we will need arg2 and arg3 later 577: clrl r2 # r2 == non-zero if source is non-zero 578: ashl $-1,r11,r11 # length is number of bytes, not nibbles 579: jeql Lmovp_zlen 580: Lmovp_copy: 581: bisb2 (r10),r2 # keep track of non-zero source 582: movb (r10)+,(r3)+ # move two nibbles 583: decl r11 # loop for length of source 584: jneq Lmovp_copy 585: Lmovp_zlen: 586: extzv $4,$4,(r10),r0 # look at least significant nibble 587: bisl2 r0,r2 588: extzv $0,$4,(r10),r0 # check sign nibble 589: cmpl r0,NEGATIVEalt 590: jeql Lmovp_neg 591: cmpl r0,NEGATIVE 592: jneq Lmovp_pos 593: Lmovp_neg: # source was negative 594: mnegl r2,r2 595: Lmovp_pos: 596: tstl r2 # set condition codes 597: savepsl 598: jeql Lmovp_zero 599: movb (r10),(r3) # move last byte if non-zero result 600: jbr Lmovp_out 601: Lmovp_zero: 602: movb POSITIVE,(r3) # otherwise, make result zero and positive 603: Lmovp_out: 604: clrl r0 605: argl(2,r1) 606: clrl r2 607: argl(3,r3) 608: return 609: 610: 611: /* 612: * Definitions for Editpc instruction 613: * 614: * Here are the commands and their corresponding hex values: 615: * 616: * EPend 0x00 617: * EPend_float 0x01 618: * EPclear_signif 0x02 619: * EPset_signif 0x03 620: * EPstore_sign 0x04 621: * EPload_fill 0x40 622: * EPload_sign 0x41 623: * EPload_plus 0x42 624: * EPload_minus 0x43 625: * EPinsert 0x44 626: * EPblank_zero 0x45 627: * EPreplace_sign 0x46 628: * EPadjust_input 0x47 629: * EPfill 0x80 630: * EPmove 0x90 631: * EPfloat 0xa0 632: * 633: * 634: * r4 is carved up as follows: 635: * 636: * ------------------------------------------- 637: * | N Z V C | 638: * ------------------------------------------- 639: * 640: * fill character is stuffed into arg5 space 641: * sign character is stuffed into arg6 space 642: */ 643: 644: #define SIGNIFBIT $0 645: #define setsignif bisl2 $1,r4 646: #define clsignif bicl2 $1,r4 647: #define OVERFLOWBIT $1 648: #define setoverflow bisl2 $2,r4 649: #define cloverflow bicl2 $2,r4 650: #define ZEROBIT $2 651: #define setzero bisl2 $4,r4 652: #define clzero bicl2 $4,r4 653: #define NEGATIVEBIT $3 654: #define setnegative bisl2 $8,r4 655: #define clnegative bicl2 $8,r4 656: #define putfill movb arg5,(r5)+ 657: #define setfill(reg) movb reg,arg5 658: #define putsign movb arg6,(r5)+ 659: #define setsign(reg) movb reg,arg6 660: 661: 662: .align 1 663: .globl _EMeditpc 664: _EMeditpc: 665: arguw(1,r11) # (1) source length == r11 666: argl(2,r10) # (2) source address == r10 667: argl(3,r3) # (3) pattern address == r3 668: argl(4,r5) # (4) destination address == r5 669: # we will need arg1 and arg2 later 670: # arg5 and arg6 are used for fill and sign - r0 is free 671: setfill($32) # fill character is ' ' 672: setsign($32) # sign character is ' ' 673: clrl r4 # clear flags 674: ashl $-1,r11,r11 # source length / 2 675: addl3 r11,r10,r2 676: extzv $4,$4,(r2),r1 # r1 == least significant nibble of source 677: L169: 678: cmpl r2,r10 679: jeql L170 680: tstb -(r2) # loop over source packed decimal number 681: jeql L169 682: incl r1 # r1 is non-zero if source is non-zero 683: L170: 684: addl3 r11,r10,r2 685: tstl r1 686: jeql L172 # source is zero - set flags 687: extzv $0,$4,(r2),r11 688: cmpl r11,NEGATIVEalt 689: jeql L9998 # source is negative - set sign and flags 690: cmpl r11,NEGATIVE 691: jneq L175 692: L9998: 693: setnegative 694: setsign($45) # sign character is '-' 695: jbr L175 696: L172: 697: setzero 698: L175: 699: arguw(1,r2) # (1) source length == r2 700: Ledit_case: 701: movzbl (r3)+,r11 # get next edit command (pattern) 702: cmpl r11,$128 703: jlss L180 704: extzv $0,$4,r11,r1 # command has a "count" arg - into r1 705: ashl $-4,r11,r11 # and shift over 706: L180: 707: jbc $6,r11,L181 # "shift" those commands > 64 to 16 and up 708: subl2 $48,r11 709: L181: 710: caseb r11,$0,$0x18 # "do" the command 711: # r11 is available for use, r1 has "count" in it 712: Lcaseb_label: 713: .word Le_end - Lcaseb_label # 00 714: .word Le_end_float - Lcaseb_label # 01 715: .word Le_clear_signif - Lcaseb_label # 02 716: .word Le_set_signif - Lcaseb_label # 03 717: .word Le_store_sign - Lcaseb_label # 04 718: .word Le_end - Lcaseb_label # 05 719: .word Le_end - Lcaseb_label # 06 720: .word Le_end - Lcaseb_label # 07 721: .word Le_fill - Lcaseb_label # 80 722: .word Le_move - Lcaseb_label # 90 723: .word Le_float - Lcaseb_label # a0 724: .word Le_end - Lcaseb_label # b0 725: .word Le_end - Lcaseb_label # c0 726: .word Le_end - Lcaseb_label # d0 727: .word Le_end - Lcaseb_label # e0 728: .word Le_end - Lcaseb_label # f0 729: .word Le_load_fill - Lcaseb_label # 40 730: .word Le_load_sign - Lcaseb_label # 41 731: .word Le_load_plus - Lcaseb_label # 42 732: .word Le_load_minus - Lcaseb_label # 43 733: .word Le_insert - Lcaseb_label # 44 734: .word Le_blank_zero - Lcaseb_label # 45 735: .word Le_replace_sign - Lcaseb_label # 46 736: .word Le_adjust_input - Lcaseb_label # 47 737: Le_end: 738: arguw(1,r0) 739: argl(2,r1) 740: clrl r2 741: decl r3 742: setpsl(r4) 743: clrl r4 744: return 745: 746: Le_end_float: 747: jbs SIGNIFBIT,r4,Ledit_case # if significance not set 748: putsign # drop in the sign 749: # fall into... 750: Le_set_signif: 751: setsignif 752: jbr Ledit_case 753: 754: Le_clear_signif: 755: clsignif 756: jbr Ledit_case 757: 758: Le_store_sign: 759: putsign 760: jbr Ledit_case 761: 762: Le_load_fill: 763: setfill((r3)+) 764: jbr Ledit_case 765: 766: Le_load_plus: 767: jbs NEGATIVEBIT,r4,Lpattern_inc # if non-negative 768: # fall into... 769: Le_load_sign: 770: setsign((r3)+) 771: jbr Ledit_case 772: 773: Le_load_minus: 774: jbs NEGATIVEBIT,r4,Le_load_sign # if negative load the sign 775: incl r3 # else increment pattern 776: jbr Ledit_case 777: 778: Le_insert: 779: jbc SIGNIFBIT,r4,L196 # if significance set, put next byte 780: movb (r3)+,(r5)+ 781: jbr Ledit_case 782: L196: # else put in fill character 783: putfill 784: # and throw away character in pattern 785: Le_replace_sign: # we don't do anything with 786: Lpattern_inc: # replace sign `cause we don't 787: incl r3 # get negative zero 788: jbr Ledit_case 789: 790: Le_blank_zero: 791: jbc ZEROBIT,r4,Lpattern_inc # if zero 792: movzbl (r3)+,r11 # next byte is a count 793: jeql Ledit_case 794: subl2 r11,r5 # to back up over output and replace 795: L200: 796: putfill # with fill character 797: decl r11 798: jneq L200 799: jbr Ledit_case 800: 801: Le_adjust_input: 802: movzbl (r3)+,r0 # get count of nibbles from pattern 803: subl3 r2,r0,r11 804: jgeq Ledit_case # if length of source is > this number 805: L204: # discard digits in source 806: jlbc r2,L206 # use low bit of length to choose nibble 807: bitb $0xf0,(r10) # high nibble 808: jeql L208 809: setsignif # set significance and overflow if 810: setoverflow # wasted digit is non-zero 811: jbr L208 812: L206: 813: bitb $0xf,(r10) # low nibble 814: jeql L209 815: setsignif 816: setoverflow 817: L209: 818: incl r10 # increment to next byte 819: L208: 820: decl r2 # decrement source length 821: incl r11 # continue `till we're out of excess 822: jlss L204 823: jbr Ledit_case 824: 825: Le_fill: 826: tstl r1 # put (count in r1) fill characters 827: jeql Ledit_case 828: Le_fill_loop: 829: putfill 830: decl r1 831: jneq Le_fill_loop 832: jbr Ledit_case 833: 834: Le_move: 835: tstl r1 # move (count in r1) characters 836: jeql Ledit_case # from source to destination 837: L214: 838: jlbc r2,L215 # read a nibble 839: extzv $4,$4,(r10),r11 840: jbr L216 841: L215: 842: extzv $0,$4,(r10),r11 843: incl r10 844: L216: 845: decl r2 # source length CAN go negative here... 846: tstl r11 847: jeql L218 # if non-zero 848: setsignif # set significance 849: L218: 850: jbc SIGNIFBIT,r4,L219 # if significance set 851: addb3 $48,r11,(r5)+ # put '0' + digit into destination 852: jbr L220 853: L219: # else put fill character 854: putfill 855: L220: 856: decl r1 857: jneq L214 858: jbr Ledit_case 859: 860: Le_float: # move with floating sign character 861: tstl r1 862: jeql Ledit_case 863: L221: 864: jlbc r2,L222 865: extzv $4,$4,(r10),r11 866: jbr L223 867: L222: 868: extzv $0,$4,(r10),r11 869: incl r10 870: L223: 871: decl r2 # source length CAN go negative here... 872: tstl r11 873: jeql L225 874: jbs SIGNIFBIT,r4,L226 875: putsign 876: L226: 877: setsignif 878: L225: 879: jbc SIGNIFBIT,r4,L227 880: addb3 $48,r11,(r5)+ 881: jbr L228 882: L227: 883: putfill 884: L228: 885: decl r1 886: jneq L221 887: jbr Ledit_case 888: 889: 890: .align 1 891: .globl _EMashp 892: _EMashp: 893: argb(1,r11) # (1) scale (number to shift) == r11 894: arguw(2,r10) # (2) source length == r10 895: argl(3,r1) # (3) source address == r1 896: argub(4,r2) # (4) rounding factor == r2 897: arguw(5,r3) # (5) destination length == r3 898: toarg(r6,3) # arg3 holds register 6 from caller 899: argl(6,r6) # (6) destination address == r6 900: # we need arg6 for later 901: # arg1 is used for temporary storage 902: # arg4 is used as general storage 903: # arg5 is used as general storage 904: ashl $-1,r3,r0 # destination length is number of bytes 905: addl2 r0,r6 # destination address == least sig nibble 906: toarg(r6,1) # save in arg1 spot for later 907: ashl $-1,r10,r0 908: addl2 r0,r1 # source address == least sig nibble 909: extzv $0,$4,(r1),r0 # determine sign of source 910: cmpl r0,NEGATIVEalt 911: jeql Lashp_neg 912: cmpl r0,NEGATIVE 913: jeql Lashp_neg 914: movb POSITIVE,(r6) 915: jbr L245 916: Lashp_neg: 917: movb NEGATIVE,(r6) 918: L245: # r3<0> counts digits going into destination 919: bisl2 $1,r3 # and is flip-flop for which nibble to 920: tstl r11 # write in destination (1 = high, 0 = low) 921: jgeq Lashp_left # (it must start out odd) 922: addl2 r11,r10 # scale is negative (right shift) 923: jgeq Lashp_right 924: clrl r10 # test for shifting whole number out 925: jbr Lashp_setround 926: Lashp_right: 927: divl3 $2,r11,r0 928: addl2 r0,r1 # source address == MSNibble to be shifted off 929: jlbc r11,L249 930: extzv $4,$4,(r1),r0 931: addl2 r0,r2 # round = last nibble to be shifted off + round 932: jbr Lashp_setround 933: L249: 934: extzv $0,$4,(r1),r0 935: addl2 r0,r2 # round = last nibble to be shifted off + round 936: Lashp_setround: # r11<0> now is flip-flop for which nibble to 937: incl r11 # read from source (1 == high, 0 == low) 938: cmpl r2,$9 # set rounding factor to one if nibble shifted 939: jleq Lashp_noround # off + round argument was 10 or greater 940: movl $1,r2 941: jbr Lashp_shift 942: Lashp_zloop: 943: jlbs r3,L257 # don't need to clear high nibble twice 944: clrb -(r6) # clear low (and high) nib of next byte in dest 945: L257: 946: decl r3 # move to next nibble in destination, but 947: jneq L258 # don't go beyond the end. 948: incl r3 949: L258: 950: decl r11 951: Lashp_left: # while scale is positive 952: jneq Lashp_zloop 953: incl r11 # r11<0> is flip-plop ... (incl sets it to one) 954: Lashp_noround: 955: clrl r2 # no more rounding 956: Lashp_shift: 957: clrl arg4 # arg4 will be used for result condition codes 958: tstl r10 959: jeql Lashp_sethigh 960: Lashp_shloop: 961: jlbc r11,L260 962: extzv $4,$4,(r1),r0 963: jbr L261 964: L260: 965: decl r1 966: extzv $0,$4,(r1),r0 967: L261: 968: incl r11 # flip the source nibble flip/flop 969: addl2 r0,r2 # round += next nibble 970: cmpl r2,$10 # if round == 10 971: jneq L262 972: clrl arg5 # then result = 0 and round = 1 973: movl $1,r2 974: jbr L263 975: L262: # else 976: movl r2,arg5 # store result and round = 0 977: clrl r2 978: L263: 979: bisl2 arg5,arg4 # remember if result was nonzero in arg4 980: decl r3 # move to next nibble early to check 981: jgeq Lashp_noovfl # if we've moved passed destination limits 982: clrl r3 # test the result for possible overflow 983: tstl arg5 # ignore zero nibbles 984: jeql L265 # if the nibble was non-zero, overflow 985: jbr Lashp_overfl 986: Lashp_noovfl: # else 987: jlbs r3,L264 988: insv arg5,$4,$4,(r6) # put the result into destination (high or low) 989: jbr L265 990: L264: 991: decl r6 992: insv arg5,$0,$4,(r6) 993: L265: 994: decl r10 # loop for length of source 995: jneq Lashp_shloop 996: 997: Lashp_sethigh: 998: jlbc r3,L266 # if we haven't set the high nibble, 999: insv r2,$4,$4,(r6) # carry the round into the high nibble 1000: clrl r2 1001: L266: 1002: argl(1,r10) # r10 = address of destination LSNibble 1003: argl(6,r3) # r3 = address of destination MSNibble 1004: movl arg4,r11 # r11 = non-zero if destination == non-zero 1005: savepsl 1006: jbr L267 1007: Lashp_zerofill: 1008: cvtlb r2,-(r6) # fill up MSNs of destination with carry or zero 1009: clrl r2 1010: L267: 1011: cmpl r3,r6 1012: jneq Lashp_zerofill 1013: tstl r2 # if carry beyond destination, overflow 1014: jneq Lashp_overfl 1015: extzv $0,$4,(r10),r0 # test for negative result 1016: cmpl r0,NEGATIVE 1017: jneq Lashp_out 1018: mnegl r11,r11 1019: savepsl 1020: jneq Lashp_out # turn -0 into 0 1021: insv POSITIVE,$0,$4,(r10) 1022: Lashp_out: 1023: clrl r0 1024: argl(3,r6) # restore r6 from stack 1025: return 1026: Lashp_overfl: # do overflow 1027: clrl r2 1028: overflowpsl 1029: jbr Lashp_out 1030: 1031: 1032: .align 1 1033: .globl _EMcvtlp 1034: _EMcvtlp: 1035: arguw(2,r10) # (2) destination length == r10 1036: argl(3,r3) # (3) destination address == r3 1037: ashl $-1,r10,r10 1038: addl2 r10,r3 # destination address points to Least Sig byte 1039: incl r10 # length is # of bytes, not nibbles 1040: argl(1,r11) # (1) source == r11 1041: savepsl 1042: jgeq Lcvtlp_pos 1043: movb NEGATIVE,(r3) # source is negative 1044: divl3 $10,r11,r0 1045: mull3 $10,r0,r1 1046: subl3 r11,r1,r2 # r2 = source mod 10 1047: mnegl r0,r11 # source = -(source / 10) 1048: jbr Lcvtlp_cvt 1049: Lcvtlp_pos: 1050: movb POSITIVE,(r3) # source is non-negative 1051: divl3 $10,r11,r0 1052: mull3 $10,r0,r1 1053: subl3 r1,r11,r2 # r2 = source mod 10 1054: movl r0,r11 # source = source / 10 1055: Lcvtlp_cvt: 1056: insv r2,$4,$4,(r3) # store least significant digit 1057: tstl r11 1058: jeql Lcvtlp_zloop 1059: Lcvtlp_loop: # while source is non-zero 1060: decl r10 # and for length of destination ... 1061: jeql Lcvtlp_over 1062: divl3 $10,r11,r1 # r1 = source / 10 1063: mull3 $10,r1,r0 1064: subl2 r0,r11 # source = source mod 10 1065: movb r11,-(r3) # store low "nibble" in next significant byte 1066: divl3 $10,r1,r11 # source = r1 / 10 1067: mull3 $10,r11,r0 1068: subl2 r0,r1 # r1 = source mod 10 1069: insv r1,$4,$4,(r3) # store high nibble 1070: tstl r11 1071: jneq Lcvtlp_loop # quit if source becomes zero 1072: Lcvtlp_zloop: # fill any remaining bytes with zeros 1073: decl r10 1074: jeql Lcvtlp_out 1075: clrb -(r3) 1076: jbr Lcvtlp_zloop 1077: Lcvtlp_over: 1078: overflowpsl 1079: Lcvtlp_out: 1080: clrl r1 # r0 is already zero 1081: clrl r2 1082: return 1083: 1084: 1085: .align 1 1086: .globl _EMcvtpl 1087: _EMcvtpl: 1088: arguw(1,r11) # (1) source length == r11 1089: argl(2,r10) # (2) source address == r10 1090: clrl r3 # r3 == destination 1091: movl r10,r1 # r1 set up now for return 1092: ashl $-1,r11,r11 # source length is number of bytes 1093: jeql Lcvtpl_zero 1094: Lcvtpl_loop: # for source length 1095: mull2 $10,r3 # destination *= 10 1096: extzv $4,$4,(r10),r0 1097: addl2 r0,r3 # destination += high nibble 1098: mull2 $10,r3 # destination *= 10 1099: extzv $0,$4,(r10),r0 1100: addl2 r0,r3 # destination += low nibble 1101: incl r10 1102: decl r11 1103: jneq Lcvtpl_loop 1104: Lcvtpl_zero: # least significant byte 1105: mull2 $10,r3 1106: extzv $4,$4,(r10),r0 1107: addl2 r0,r3 # dest = 10 * dest + high nibble 1108: savepsl 1109: extzv $0,$4,(r10),r2 # test sign nibble 1110: cmpl r2,NEGATIVE 1111: jeql Lcvtpl_neg 1112: cmpl r2,NEGATIVEalt 1113: jneq Lcvtpl_out 1114: Lcvtpl_neg: # source was negative - negate destination 1115: mnegl r3,r3 1116: savepsl 1117: Lcvtpl_out: 1118: toarg(r3,3) 1119: clrl r0 1120: clrl r2 1121: clrl r3 1122: return 1123: 1124: 1125: .align 1 1126: .globl _EMcvtps 1127: _EMcvtps: 1128: return 1129: 1130: 1131: .align 1 1132: .globl _EMcvtsp 1133: _EMcvtsp: 1134: return 1135: 1136: 1137: .align 1 1138: .globl _EMaddp6 1139: _EMaddp6: 1140: return 1141: 1142: 1143: .align 1 1144: .globl _EMsubp4 1145: _EMsubp4: 1146: return 1147: 1148: 1149: .align 1 1150: .globl _EMsubp6 1151: _EMsubp6: 1152: return 1153: 1154: 1155: .align 1 1156: .globl _EMcvtpt 1157: _EMcvtpt: 1158: return 1159: 1160: 1161: .align 1 1162: .globl _EMmulp 1163: _EMmulp: 1164: return 1165: 1166: 1167: .align 1 1168: .globl _EMcvttp 1169: _EMcvttp: 1170: return 1171: 1172: 1173: .align 1 1174: .globl _EMdivp 1175: _EMdivp: 1176: return 1177: 1178: 1179: .align 1 1180: .globl _EMcmpp3 1181: _EMcmpp3: 1182: return 1183: 1184: 1185: .align 1 1186: .globl _EMcmpp4 1187: _EMcmpp4: 1188: return 1189: 1190: 1191: #endif UVAXII 1192: 1193: 1194: #ifdef notdef 1195: /* 1196: * Emulation OpCode jump table: 1197: * ONLY GOES FROM 0xf8 (-8) TO 0x3B (59) 1198: */ 1199: #define EMUTABLE 0x43 1200: #define NOEMULATE .long noemulate 1201: #define EMULATE(a) .long _EM/**/a 1202: .globl _emJUMPtable 1203: _emJUMPtable: 1204: /* f8 */ EMULATE(ashp); EMULATE(cvtlp); NOEMULATE; NOEMULATE 1205: /* fc */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE 1206: /* 00 */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE 1207: /* 04 */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE 1208: /* 08 */ EMULATE(cvtps); EMULATE(cvtsp); NOEMULATE; EMULATE(crc) 1209: /* 0c */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE 1210: /* 10 */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE 1211: /* 14 */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE 1212: /* 18 */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE 1213: /* 1c */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE 1214: /* 20 */ EMULATE(addp4); EMULATE(addp6); EMULATE(subp4); EMULATE(subp6) 1215: /* 24 */ EMULATE(cvtpt); EMULATE(mulp); EMULATE(cvttp); EMULATE(divp) 1216: /* 28 */ NOEMULATE; EMULATE(cmpc3); EMULATE(scanc); EMULATE(spanc) 1217: /* 2c */ NOEMULATE; EMULATE(cmpc5); EMULATE(movtc); EMULATE(movtuc) 1218: /* 30 */ NOEMULATE; NOEMULATE; NOEMULATE; NOEMULATE 1219: /* 34 */ EMULATE(movp); EMULATE(cmpp3); EMULATE(cvtpl); EMULATE(cmpp4) 1220: /* 38 */ EMULATE(editpc); EMULATE(matchc); EMULATE(locc); EMULATE(skpc) 1221: 1222: /* 1223: * The following is called with the stack set up as follows: 1224: * 1225: * (sp): Opcode 1226: * 4(sp): Instruction PC 1227: * 8(sp): Operand 1 1228: * 12(sp): Operand 2 1229: * 16(sp): Operand 3 1230: * 20(sp): Operand 4 1231: * 24(sp): Operand 5 1232: * 28(sp): Operand 6 1233: * 32(sp): Operand 7 (unused) 1234: * 36(sp): Operand 8 (unused) 1235: * 40(sp): Return PC 1236: * 44(sp): Return PSL 1237: * 48(sp): TOS before instruction 1238: * 1239: * Each individual routine is called with the stack set up as follows: 1240: * 1241: * (sp): Return address of trap handler 1242: * 4(sp): Opcode (will get return PSL) 1243: * 8(sp): Instruction PC 1244: * 12(sp): Operand 1 1245: * 16(sp): Operand 2 1246: * 20(sp): Operand 3 1247: * 24(sp): Operand 4 1248: * 28(sp): Operand 5 1249: * 32(sp): Operand 6 1250: * 36(sp): saved register 11 1251: * 40(sp): saved register 10 1252: * 44(sp): Return PC 1253: * 48(sp): Return PSL 1254: * 52(sp): TOS before instruction 1255: */ 1256: 1257: SCBVEC(emulate): 1258: movl r11,32(sp) # save register r11 in unused operand 1259: movl r10,36(sp) # save register r10 in unused operand 1260: cvtbl (sp),r10 # get opcode 1261: addl2 $8,r10 # shift negative opcodes 1262: subl3 r10,$EMUTABLE,r11 # forget it if opcode is out of range 1263: bcs noemulate 1264: movl _emJUMPtable[r10],r10 # call appropriate emulation routine 1265: jsb (r10) # routines put return values into regs 0-5 1266: movl 32(sp),r11 # restore register r11 1267: movl 36(sp),r10 # restore register r10 1268: insv (sp),$0,$4,44(sp) # and condition codes in Opcode spot 1269: addl2 $40,sp # adjust stack for return 1270: rei 1271: noemulate: 1272: addl2 $48,sp # adjust stack for 1273: .word 0xffff # "reserved instruction fault" 1274: SCBVEC(emulateFPD): 1275: .word 0xffff # "reserved instruction fault" 1276: #endif