| 1 |
98 |
Agner |
/*************************** print_integer_light.as **************************
|
| 2 |
|
|
* Author: Agner Fog
|
| 3 |
|
|
* date created: 2021-05-16
|
| 4 |
|
|
* Last modified: 2021-05-16
|
| 5 |
|
|
* Version: 1.11
|
| 6 |
|
|
* Project: ForwardCom library libc_light.li
|
| 7 |
|
|
* Description: puts: print a string to stdout. Does not append linefeed
|
| 8 |
|
|
* This version is for CPUs with limited capabilities
|
| 9 |
|
|
* C declaration: void print_integer(int32_t i);
|
| 10 |
|
|
* C declaration: void print_unsigned(uint32_t i);
|
| 11 |
|
|
*
|
| 12 |
|
|
* Copyright 2021 GNU General Public License http://www.gnu.org/licenses
|
| 13 |
|
|
******************************************************************************/
|
| 14 |
|
|
|
| 15 |
|
|
code section execute align = 4 // code section
|
| 16 |
|
|
|
| 17 |
|
|
// Print a 32-bit signed integer as decimal number to stdout
|
| 18 |
|
|
_print_integer function public reguse=3,0
|
| 19 |
|
|
|
| 20 |
|
|
if (int32 r0 < 0) {
|
| 21 |
|
|
int32 r0 = -r0
|
| 22 |
|
|
int8+ r1 = '-'
|
| 23 |
|
|
int8 output(r1, r1, 10) // print '-'
|
| 24 |
|
|
}
|
| 25 |
|
|
// continue in _print_unsigned
|
| 26 |
|
|
|
| 27 |
|
|
// Print a 32-bit unsigned integer as decimal number to stdout
|
| 28 |
|
|
_print_unsigned function public reguse=3,0
|
| 29 |
|
|
|
| 30 |
|
|
// This function is using the double dabble algorithm for binary to BCD conversion.
|
| 31 |
|
|
// This method is slow, but it is used here because it does not require division
|
| 32 |
|
|
// or multiplication. This makes sure it will work on small cores without mul and div instructions.
|
| 33 |
|
|
|
| 34 |
|
|
// save r2-r5
|
| 35 |
|
|
int64 sp -= 4*8
|
| 36 |
|
|
int64 [sp] = r2
|
| 37 |
|
|
int64 [sp+8] = r3
|
| 38 |
|
|
int64 [sp+0x10] = r4
|
| 39 |
|
|
int64 [sp+0x18] = r5
|
| 40 |
|
|
|
| 41 |
|
|
// First two BCD digits are made with simple subtraction to avoid the need for a larger bit field
|
| 42 |
|
|
int r5 = 0
|
| 43 |
|
|
while (uint32 r0 >= 1000000000) {
|
| 44 |
|
|
uint32 r0 -= 1000000000
|
| 45 |
|
|
uint32 r5 += 0x10
|
| 46 |
|
|
}
|
| 47 |
|
|
while (uint32 r0 >= 100000000) {
|
| 48 |
|
|
uint32 r0 -= 100000000
|
| 49 |
|
|
uint32 r5 += 0x01
|
| 50 |
|
|
}
|
| 51 |
|
|
uint32 r5 <<= 24
|
| 52 |
|
|
|
| 53 |
|
|
// Generate 8 BCD digits using double dabble algorithm
|
| 54 |
|
|
int32 r1 = 0
|
| 55 |
|
|
for (int r2 = 0; r2 < 32; r2++) { // loop for 32 bits
|
| 56 |
|
|
int32 r3 = r1 + 0x33333333 // digit values 5-9 will set bit 3 in each 4-bit nibble
|
| 57 |
|
|
int32 r3 &= 0x88888888 // isolate bit 3 in each nibble
|
| 58 |
|
|
int32 r4 = r3 >> 3 // generate value 3 in nibbles with value 5-9
|
| 59 |
|
|
int32 r3 >>= 2
|
| 60 |
|
|
int32 r3 |= r4 // this will have 3 for each nibble with a value 5-9
|
| 61 |
|
|
int32 r1 += r3 // add 3 to nibble values 5-9 to generate 8-12
|
| 62 |
|
|
int32 r1 = funnel_shift(r0, r1, 31) // shift most significant bit of r0 into r1
|
| 63 |
|
|
int32 r0 <<= 1
|
| 64 |
|
|
}
|
| 65 |
|
|
|
| 66 |
|
|
// r5:r1 = BCD value
|
| 67 |
|
|
|
| 68 |
|
|
int r4 = 0 // remember if first digit has been printed
|
| 69 |
|
|
|
| 70 |
|
|
for (int r2 = 2; r2 > 0; r2--) {
|
| 71 |
|
|
int32 r5 = rotate(r5, 4) // get most significant digit first
|
| 72 |
|
|
int8 r3 = r5 & 0x0F
|
| 73 |
|
|
int r4 = (r3 != 0) || r4 // digit has been printed
|
| 74 |
|
|
int8 r3 += '0'
|
| 75 |
|
|
if (int r4 != 0) {
|
| 76 |
|
|
int8 output(r3, r3, 10) // print character to stdout
|
| 77 |
|
|
}
|
| 78 |
|
|
}
|
| 79 |
|
|
|
| 80 |
|
|
// print 8 decimal digits
|
| 81 |
|
|
for (int r2 = 8; r2 > 0; r2--) {
|
| 82 |
|
|
int32 r1 = rotate(r1, 4) // get most significant digit first
|
| 83 |
|
|
int8 r3 = r1 & 0x0F
|
| 84 |
|
|
int r4 = (r3 != 0) || r4 // digit has been printed
|
| 85 |
|
|
int r4 = (r2 == 1) || r4 // last digit must be printed
|
| 86 |
|
|
int8 r3 += '0'
|
| 87 |
|
|
if (int r4 != 0) {
|
| 88 |
|
|
int8 output(r3, r3, 10) // print character to stdout
|
| 89 |
|
|
}
|
| 90 |
|
|
}
|
| 91 |
|
|
|
| 92 |
|
|
// restore r2-r5
|
| 93 |
|
|
int64 r2 = [sp]
|
| 94 |
|
|
int64 r3 = [sp+8]
|
| 95 |
|
|
int64 r4 = [sp+0x10]
|
| 96 |
|
|
int64 r5 = [sp+0x18]
|
| 97 |
|
|
int64 sp += 4*8
|
| 98 |
|
|
return
|
| 99 |
|
|
_print_integer end
|
| 100 |
|
|
|
| 101 |
|
|
code end
|