block Number { // char toDigit( long value ) { // if ( value < 0 || 36 <= value ) // error( "Invalid invocation of toDigit()" ); // else if ( value < 10 ) // return value + '0'; // else // return value + 'a' - 10; // } private block toDigit uses proc { const { align quad; message: asciiz "Invalid invocation of toDigit()"; align quad; } code { public enter: body: { if: cmpult $a0, 36, $t0; blbs $t0, elif; then1: ldiq $a0, message; bsr IO.error.enter; elif: cmpult $a0, 10, $t0; blbc $t0, else; then2: addq $a0, '0', $v0; br end; else: addq $a0, 'a' - 10, $v0; end: } return: ret; } } // long fromDigit( char c, long base ) { // long value; // if ( '0' <= c && c <= '9' ) // value = c - '0'; // else if ( 'a' <= c && c <= 'z' ) // value = c - 'a' + 10; // else if ( 'A' <= c && c <= 'Z' ) // value = c - 'A' + 10; // else // value = -1; // if ( value >= base ) // return -1; // else // return value; // } private block fromDigit uses proc { abs { c = a0; base = a1; } code { public enter: body: { if: cmpult $c, '0', $t0; blbs $t0, elif1; cmpule $c, '9', $t0; blbc $t0, elif1; then1: subq $c, '0', $v0; br end; elif1: cmpult $c, 'a', $t0; blbs $t0, elif2; cmpule $c, 'z', $t0; blbc $t0, elif2; then2: subq $c, 'a' - 10, $v0; br end; elif2: cmpult $c, 'A', $t0; blbs $t0, else; cmpule $c, 'Z', $t0; blbc $t0, else; then3: subq $c, 'A' - 10, $v0; br end; else: negq 1, $v0; end: } { if: cmplt $v0, $base, $t0; blbs $t0, end; then: negq 1, $v0; end: } return: ret; } } // long fromString( char *buffer, long base ) { // long result = 0; // long sign = 1; // long d; // if ( *buffer == '-' ) { // sign = -1; // buffer++; // } // else if ( *buffer == '+' ) { // buffer++; // } // if ( base == 0 ) { // if ( *buffer >= '1' && *buffer <= '9' ) // base = 10; // else if ( *buffer == '0' ) { // buffer++; // if ( *buffer == 'x' || *buffer == 'X' ) { // buffer++; // base = 16; // } // else // base = 8; // } // } // while ( TRUE ) { // d = fromDigit( *buffer, base ); // if ( d < 0 ) // if ( *buffer == NULL ) // return result; // else // return 1<<63; // Error indication // result = result * base + d; // buffer++; // } // return sign * result; // } public block fromString uses proc { abs { buffer = s0; base = s1; result = s2; sign = s3; } code { public enter: lda $sp, -sav4($sp); stq $ra, savRA($sp); stq $s0, sav0($sp); stq $s1, sav1($sp); stq $s2, sav2($sp); stq $s3, sav3($sp); decl: mov $a0, $buffer; mov $a1, $base; body: clr $result; mov 1, $sign; { if: ldbu $t1, ($buffer); cmpeq $t1, '-', $t2; blbs $t2, then1; cmpeq $t1, '+', $t2; blbs $t2, then2; br end; then1: addq $buffer, 1; negq 1, $sign; br end; then2: addq $buffer, 1; end: } { if: bne $base, end; ldbu $t1, ($buffer); cmplt $t1, '1', $t2; blbs $t2, else; cmple $t1, '9', $t2; blbc $t2, else; decimal: mov 10, $base; br end; else: cmpeq $t1, '0', $t2; blbc $t2, end; addq $buffer, 1; ldbu $t1, ($buffer); cmpeq $t1, 'x', $t2; blbs $t2, hexadecimal; cmpeq $t1, 'X', $t2; blbs $t2, hexadecimal; octal: mov 8, $base; br end; hexadecimal: mov 16, $base; addq $buffer, 1; end: } { while: ldbu $a0, ($buffer); // Get character mov $base, $a1; bsr fromDigit.enter; { if: bge $v0, end; { if: ldbu $t0, ($buffer); // Get character bne $t0, else; then: mov $result, $v0; br return; else: ldiq $v0, 1<<63; br return; end: } then: end: } do: mulq $result, $base; // result = result * base + fromdigit( *s ); addq $result, $v0; addq $buffer, 1; br while; end: } mulq $result, $sign, $v0; return: ldq $s3, sav3($sp); ldq $s2, sav2($sp); ldq $s1, sav1($sp); ldq $s0, sav0($sp); ldq $ra, savRA($sp); lda $sp, +sav4($sp); ret; } } // #define MAXBUFFER 65 // char *toUnsigned( unsigned long value, long base ) { // static char buffer[ MAXBUFFER + 1 ]; // char *ptr = buffer + MAXBUFFER; // if ( value == 0 ) // return "0"; // else { // *ptr = 0; // while ( value > 0 ) { // --ptr; // *ptr = toDigit( value % base ); // value = value / base; // } // } // } public block toUnsigned uses proc { abs { MAXBUFFER = 65; value = s0; base = s1; fieldWidth = s2; ptr = s3; } data { align quad; buffer: ubyte[ MAXBUFFER + 1 ]; align quad; } code { public enter: lda $sp, -sav4($sp); stq $ra, savRA($sp); stq $s0, sav0($sp); stq $s1, sav1($sp); stq $s2, sav2($sp); stq $s3, sav3($sp); decl: mov $a0, $value; mov $a1, $base; body: ldiq $t0, buffer; addq $t0, MAXBUFFER, $ptr; // ptr = buffer + MAXBUFFER; stb $zero, ($ptr); { if: bne $value, else; then: subq $ptr, 1; ldiq $t0, '0'; stb $t0, ($ptr); br end; else: { while: beq $value, end; do: subq $ptr, 1; modqu $value, $base, $a0; bsr toDigit.enter; stb $v0, ($ptr); divqu $value, $base; br while; end: } end: } mov $ptr, $v0; return: ldq $s3, sav3($sp); ldq $s2, sav2($sp); ldq $s1, sav1($sp); ldq $s0, sav0($sp); ldq $ra, savRA($sp); lda $sp, +sav4($sp); ret; } } // char *toSigned( long value, long base ) { // char *result; // if ( value < 0 ) { // result = toUnsigned( - value, base ); // *--result = '-'; // } // else // result = toUnsigned( value, base ); // return result; // } public block toSigned uses proc { abs { value = s0; base = s1; result = s2; } code { public enter: lda $sp, -sav3($sp); stq $ra, savRA($sp); stq $s0, sav0($sp); stq $s1, sav1($sp); stq $s2, sav2($sp); decl: mov $a0, $value; mov $a1, $base; body: { if: bge $value, else; then: negq $value, $a0; mov $base, $a1; bsr toUnsigned.enter; subq $v0, 1, $result; ldiq $t0, '-'; stb $t0, ($result); br end; else: mov $value, $a0; mov $base, $a1; bsr toUnsigned.enter; mov $v0, $result; end: } mov $result, $v0; return: ldq $s2, sav2($sp); ldq $s1, sav1($sp); ldq $s0, sav0($sp); ldq $ra, savRA($sp); lda $sp, +sav3($sp); ret; } } // char *doubleToString( double value, long places ) { // long exponent = 0; // long digit; // static char buffer[ MAXBUFFER + 1 ]; // char *ptr = buffer; // char *exponentText; // if ( value < 0.0 ) { // *ptr++ = '-'; // value = - value; // } // if ( value > 0.0 ) { // while ( value < 1.0 ) { // exponent = exponent - 1; // value = 10.0 * value; // } // while ( value >= 10.0 ) { // exponent = exponent + 1; // value = value / 10.0; // } // } // digit = entier( value ); // value = ( value - digit ) * 10.0; // *ptr++ = toDigit( digit ); // *ptr++ = '.'; // while ( places > 0 ) { // digit = entier( value ); // *ptr++ = toDigit( digit ); // value = ( value - digit ) * 10; // --places; // } // *ptr++ = 'e'; // exponentText = toSigned( exponent, 10 ); // strcpy( ptr, exponentText ); // return buffer; // } public block doubleToString uses proc { abs { MAXBUFFER = 65; value = fs0; places = s1; exponent = s2; ptr = s3; digit = s4; exponentText = s5; } data { align quad; buffer: byte[ MAXBUFFER + 1 ]; } code { public enter: lda $sp, -sav6($sp); stq $ra, savRA($sp); stt $fs0, sav0($sp); stq $s1, sav1($sp); stq $s2, sav2($sp); stq $s3, sav3($sp); stq $s4, sav4($sp); stq $s5, sav5($sp); fmov $fa0, $value; mov $a1, $places; body: clr $exponent; ldiq $ptr, buffer; { if: fbge $value, end; then: mov '-', $t0; stb $t0, ($ptr); addq $ptr, 1; negt $value, $value; end: } { if: fbeq $value, end; then: { while: ldit $ft0, 1.0; cmptlt $value, $ft0, $ft0; fbeq $ft0, end; do: subq $exponent, 1; ldit $ft0, 10.0; mult $value, $ft0; br while; end: } { while: ldit $ft0, 10.0; cmptlt $value, $ft0, $ft0; fbne $ft0, end; do: addq $exponent, 1; ldit $ft0, 10.0; divt $value, $ft0; br while; end: } end: } cvttq $value, $ft0; ftoit $ft0, $digit; cvtqt $ft0, $ft0; subt $value, $ft0; ldit $ft0, 10.0; mult $value, $ft0; addq $digit, '0'; stb $digit, ($ptr); addq $ptr, 1; mov '.', $t0; stb $t0, ($ptr); addq $ptr, 1; { while: beq $places, end; do: cvttq $value, $ft0; ftoit $ft0, $digit; cvtqt $ft0, $ft0; subt $value, $ft0; ldit $ft0, 10.0; mult $value, $ft0; addq $digit, '0'; stb $digit, ($ptr); addq $ptr, 1; subq $places, 1; br while; end: } mov 'e', $t0; stb $t0, ($ptr); addq $ptr, 1; mov $exponent, $a0; mov 10, $a1; bsr toSigned.enter; mov $ptr, $a0; mov $v0, $a1; bsr String.copy.enter; ldiq $v0, buffer; return: ldq $s5, sav5($sp); ldq $s4, sav4($sp); ldq $s3, sav3($sp); ldq $s2, sav2($sp); ldq $s1, sav1($sp); ldt $fs0, sav0($sp); ldq $ra, savRA($sp); lda $sp, +sav6($sp); ret; } } }