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