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