OpenCores
URL https://opencores.org/ocsvn/forwardcom/forwardcom/trunk

Subversion Repositories forwardcom

[/] [forwardcom/] [libraries/] [printf_light.as] - Blame information for rev 101

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 101 Agner
/****************************  printf_light.as ********************************
2
* Author:        Agner Fog
3
* date created:  2021-05-24
4
* Last modified: 2021-05-25
5
* Version:       1.11
6
* Project:       ForwardCom library libc_light.li
7
* Description:   printf, sprintf, snprintf: Print formatted output
8
* This version is for small CPUs with limited capabilities
9
* The following instructions are avoided: mul, div, push, pop, sys_call.
10
* Output to stdout goes directly to output port 10. It does not wait if
11
* the output buffer is full.
12
*
13
* C declarations:
14
* int printf   (const char * format, ... );
15
* int sprintf  (char * string, const char * format, ... );
16
* int snprintf (char * string, size_t max_length, const char * format, ... );
17
*
18
* printf:   print to stdout
19
* sprintf:  print to string
20
* snprintf: print to string with length limit
21
* fprintf:  print to file. not implemented yet
22
*
23
* These functions are following the definitions in the C standard.
24
* All standard features are supported, except the following:
25
* - cannot print floating point numbers
26
* - cannot print octal
27
* - cannot print decimal integers with more than 32 bits
28
*
29
* Copyright 2021 GNU General Public License http://www.gnu.org/licenses
30
*****************************************************************************/
31
 
32
const section read ip
33
 
34
// call table for dispatching format string specifiers
35
call_table: int8  (specif_space-def)/4 // ' ': print space or minus
36
int8  0                                // !
37
int8  0                                // "
38
int8  (specif_hash-def)/4              // #: prepend 0x
39
int8  0                                // $
40
int8  (specif_percent-def)/4           // %: print percent sign
41
int8  0                                // &
42
int8  0                                // '
43
int8  0                                // (
44
int8  0                                // )
45
int8  (specif_star-def)/4              // *: width specified by parameter
46
int8  (specif_plus-def)/4              // +: print sign
47
int8  0                                // ,
48
int8  (specif_minus-def)/4             // -: left justified
49
int8  0                                // .
50
int8  0                                // /
51
int8  (specif_number-def)/4            // 0
52
int8  (specif_number-def)/4            // 1
53
int8  (specif_number-def)/4            // 2
54
int8  (specif_number-def)/4            // 3
55
int8  (specif_number-def)/4            // 4
56
int8  (specif_number-def)/4            // 5
57
int8  (specif_number-def)/4            // 6
58
int8  (specif_number-def)/4            // 7
59
int8  (specif_number-def)/4            // 8
60
int8  (specif_number-def)/4            // 9
61
int8  0                                // :
62
int8  0                                // ;
63
int8  0                                // <
64
int8  0                                // =
65
int8  0                                // >
66
int8  0                                // ?
67
int8  0                                // @
68
int8  (specif_hex-def)/4               // A: hexadecimal float
69
int8  0                                // B
70
int8  0                                // C
71
int8  0                                // D
72
int8  (specif_float-def)/4             // E: float
73
int8  (specif_float-def)/4             // F: float
74
int8  (specif_float-def)/4             // G: float
75
int8  0                                // H
76
int8  0                                // I
77
int8  0                                // J
78
int8  0                                // K
79
int8  (specif_l-def)/4                 // L: long (long double)
80
int8  0                                // M
81
int8  0                                // N
82
int8  0                                // O
83
int8  0                                // P
84
int8  0                                // Q
85
int8  0                                // R
86
int8  0                                // S
87
int8  0                                // T
88
int8  0                                // U
89
int8  0                                // V
90
int8  0                                // W
91
int8  (specif_hex-def)/4               // X: hexadecimal
92
int8  0                                // Y
93
int8  0                                // Z
94
int8  0                                // [
95
int8  0                                // \
96
int8  0                                // ]
97
int8  0                                // ^
98
int8  0                                // _
99
int8  0                                // `
100
int8  (specif_hex-def)/4               // a: hexadecimal float
101
int8  0                                // b
102
int8  (specif_char-def)/4              // c: character
103
int8  (specif_dec-def)/4               // d: signed decimal
104
int8  (specif_float-def)/4             // e: float
105
int8  (specif_float-def)/4             // f: float
106
int8  (specif_float-def)/4             // g: float
107
int8  (specif_h-def)/4                 // h: short
108
int8  (specif_dec-def)/4               // i: signed decimal
109
int8  (specif_l-def)/4                 // j: intmax_t
110
int8  0                                // k
111
int8  (specif_l-def)/4                 // l: long
112
int8  0                                // m
113
int8  (specif_num-def)/4               // n: read number of characters printed so far
114
int8  0                                // o
115
int8  (specif_hex-def)/4               // p: pointer, print as hexadecimal
116
int8  0                                // q
117
int8  0                                // r
118
int8  (specif_string-def)/4            // s: string
119
int8  (specif_l-def)/4                 // t: ptrdiff_t
120
int8  (specif_uns-def)/4               // u: unsigned decimal
121
int8  0                                // v
122
int8  0                                // w
123
int8  (specif_hex-def)/4               // x: hexadecimal
124
int8  0                                // y
125
int8  (specif_l-def)/4                 // z: size_t
126
const end
127
 
128
code section execute align = 4         // code section
129
 
130
 
131
// _printf: print formatted string to stdout
132
// parameters: r0: format string, r1: parameter list
133
_printf function public reguse = 0xF, 0
134
  int64 r2 = r0                        // format string
135
  int64 r3 = r1                        // parameter list
136
  int64 sp -= 10*8                     // start saving registers
137
  int64 [sp+0x30] = r10                // save r10. The rest are saved under printf_generic
138
  int64 r10 = address ([char_to_stdout])
139
  jump printf_generic
140
 
141
 
142
// _sprintf: print formatted string to string buffer
143
// parameters: r0: destination string, r1: format string, r2: parameter list
144
_sprintf function public reguse = 0xF, 0
145
  int64 r3 = r2                        // parameter list
146
  int64 r2 = r1                        // format string
147
  int64 r1 = -1                        // character count limit = UINT_MAX
148
  int64 sp -= 10*8                     // start saving registers
149
  int64 [sp+0x30] = r10                // save r10. The rest are saved under printf_generic
150
  int64 r10 = address ([char_to_string])
151
  jump printf_generic
152
 
153
 
154
// _snprintf: print formatted string to string buffer with limit
155
// parameters: r0: destination string, r1: length limit, r2: format string, r3: parameter list
156
_snprintf function public reguse = 0xF, 0
157
  int64 r1--                           // character count limit. make space for terminating zero
158
  int64 sp -= 10*8                     // start saving registers
159
  int64 [sp+0x30] = r10                // save r10. The rest are saved under printf_generic
160
  int64 r10 = address ([char_to_string])
161
  // continue in printf_generic
162
 
163
printf_generic:                        // common procedure for all printf variants
164
  // save r4 - r13
165
  //int64 sp -= 10*8                   // this is done above
166
  int64 [sp+0x00] = r4
167
  int64 [sp+0x08] = r5
168
  int64 [sp+0x10] = r6
169
  int64 [sp+0x18] = r7
170
  int64 [sp+0x20] = r8
171
  int64 [sp+0x28] = r9
172
  // int64 [sp+0x30] = r10             // r10 saved above
173
  int64 [sp+0x38] = r11
174
  int64 [sp+0x40] = r12
175
  int64 [sp+0x48] = r13
176
 
177
  if (int64 r2 == 0) {jump finish}     // format string pointer is null
178
  int r13  = 0                         // reset field width
179
  int r11 = 0                          // reset modifiers
180
  int r12 = 0                          // state start
181
 
182
  // loop through format string
183
  while (true) {
184
    int8 r8 = [r2]                     // read character from format string
185
    if (int8+ r8 == 0) {break}         // end of format string
186
    int64 r2++                         // increment format string pointer
187
 
188
    if (int r12 == 0) {                // state start
189
 
190
      if (int8+ r8 == '%') {
191
        int r12 = 1                    // state after '%'
192
      }
193
      else {
194
        call (r10)                     // print character from format string
195
      }
196
      nop
197
 
198
    }
199
    else {                             // after '%' or modifier
200
      int r6 = r8 - ' '                // table index
201
      int64 r4 = address ([unknown_character])
202
      if (uint r6 > 91) {
203
        call (r4)                      // call unknown_character
204
      }
205
      else {
206
        int64 r5 = address ([call_table])
207
        int8 call_relative (r4, [r5 + r6*1])  // dispatch format specifier or modifier
208
      }
209
    }
210
  }
211
  finish:
212
 
213
  // if printing to string, insert terminating zero
214
  int64 r4 = address ([char_to_string])
215
  if (uint64 r10 >= r4) {
216
    int r4 = 0
217
    int8 [r0] = r4
218
  }
219
  int64 r0 = r9                        // return number of characters written
220
 
221
  // restore r4 - r13
222
  int64 r4  = [sp+0x00]
223
  int64 r5  = [sp+0x08]
224
  int64 r6  = [sp+0x10]
225
  int64 r7  = [sp+0x18]
226
  int64 r8  = [sp+0x20]
227
  int64 r9  = [sp+0x28]
228
  int64 r10 = [sp+0x30]
229
  int64 r11 = [sp+0x38]
230
  int64 r12 = [sp+0x40]
231
  int64 r13 = [sp+0x48]
232
  int64 sp += 10*8
233
  return                               // return from _printf, etc.
234
 
235
 
236
/////////////////////////////////////////////////////////////
237
// subfunctions for different characters in format string
238
/////////////////////////////////////////////////////////////
239
 
240
specif_space:                          // ' ': print space or minus
241
  if (int r12 != 1) {jump unknown_character}
242
  int r11 |= 8                         // set modifier flag
243
  return
244
 
245
specif_plus:                           // +: print sign
246
  if (int r12 != 1) {jump unknown_character}
247
  int r11 |= 4                         // set modifier flag
248
  return
249
 
250
specif_minus:                          // -: left justified
251
  if (int r12 != 1) {jump unknown_character}
252
  int r11 |= 1                         // set modifier flag
253
  return
254
 
255
specif_hash:                           // hash sign: print prefix 0x
256
  if (int r12 != 1) {jump unknown_character}
257
  int r11 |= 0x10                      // set modifier flag
258
  return
259
 
260
specif_h:                              // h: short
261
  int r4 = test_bits_or(r11, 0x40)     // is there a preceding h?
262
  int r11 |= 0x40                      // set modifier flag h
263
  int r11 |= 0x80, mask = r4           // set modifier flag hh
264
  int r12 = 3                          // state after sub_specifier
265
  return
266
 
267
specif_l:                              // l: long
268
  int r11 |= 0x20                      // set modifier flag l
269
  int r12 = 3                          // state after sub_specifier
270
  return
271
 
272
specif_percent:                        // %: print percent sign
273
  jump unknown_character               // just print % sign and reset state
274
 
275
specif_star:                           // *: width specified by parameter
276
  if (int r12 != 1) {jump unknown_character}
277
  int r13 = [r3]                        // read width from paramter
278
  int64 r3 += 8
279
  int r12 = 2                          // state after width
280
  int r11 |= 0x100                     // set modifier flag
281
  return
282
 
283
specif_number:                         // 0-9
284
  if (int r12 == 1) {
285
    if (int r8 == '0') {               // leading '0' means print leading zeroes
286
      int r11 |= 2                     // set modifier flag 2
287
      return
288
    }
289
  }
290
  // number specifies width
291
  // width = previous_width * 10 + new_digit
292
  int r4 = r13 << 3                     // multiply width by 10
293
  int r13 <<= 1
294
  int r13 += r4
295
  int r8 -= '0'                        // convert from ASCII
296
  int r13 += r8                        // new width
297
  int r12 = 2                          // state after width
298
  int r11 |= 0x100                     // set modifier flag
299
  return
300
 
301
// subfunction for writing to stdout
302
char_to_stdout:
303
  int8 output(r8, r8, 10)              // write to stdout
304
  int64 r9++                           // count characters written
305
  return
306
 
307
// subfunction for writing to string
308
char_to_string:
309
  int64 r9++                           // count characters written or potentially written
310
  if (uint64 r9 > r1) {                // compare with string length limit
311
    jump char_to_string9               // stop printing
312
  }
313
  int8 [r0] = r8                       // write to string
314
  int64 r0++                           // increment string pointer
315
char_to_string9:
316
  return
317
 
318
 
319
// %n: read number of characters printed so far
320
specif_num:                            // n: read number of characters printed so far
321
  int64 r4 = [r3]                      // read pointer from parameter list
322
  int64 r3 += 8                        // increment parameter list
323
  int32 [r4] = r9                      // save number of characters written
324
  jump reset_state
325
 
326
 
327
// %c: Print character
328
specif_char:                           // c: print character
329
  int r13--                            // number of leading or trailing spaces to pring
330
  if (int !(r11 & 1)) {                // field is right justified. print leading spaces
331
    int r8 = ' '                       // leading spaces
332
    for (int; r13 > 0; r13--) {
333
      call (r10)                       // print space
334
    }
335
  }
336
  int8 r8 = [r3]                       // read character from parameter list
337
  int64 r3 += 8                        // increment parameter list
338
  call (r10)                           // print character
339
  int r8 = ' '                         // print any trailing spaces
340
  for (int; r13 > 0; r13--) {
341
    call (r10)                         // print space
342
  }
343
  jump reset_state
344
 
345
 
346
// %s: Print string
347
specif_string:                         // s: string
348
  int64 r6 = [r3]                      // read string pointer from parameter list
349
  int64 r3 += 8                        // increment parameter list
350
  if (int64 r6 == 0) {jump unknown_character} // null string
351
  int r4 = r11 ^ 1                     // check if right justified
352
  int16+ test_bits_and(r4, 0x101), jump_false specif_string2
353
  // string is right justified with specified width. check if leading spaces are needed
354
  for (int r5 = 0; r5 < r13; r5++) {
355
    int8 r8 = [r6+r5]                  // read string character
356
    if (int8+ r8 == 0) {break}         // string is shorter. leading spaces needed
357
  }
358
  // print leading spaces
359
  int r8 = ' '
360
  for (int ; r5 < r13; r5++) {
361
    call (r10)                         // print space
362
  }
363
  int r13 = 0                           // avoid printing trailing spaces also
364
  specif_string2:
365
  while (true) {
366
    int8 r8 = [r6]                     // read character from string
367
    if (int8+ r8 == 0) {break}         // end of string
368
    int64 r6++                         // increment string pointer
369
    call (r10)                         // print character
370
    int r13--                           // count down field width
371
  }
372
  // print any trailing space
373
  int r8 = ' '
374
  while (int r13 > 0) {
375
    call (r10)                         // print character
376
    int r13--                           // count down field width
377
  }
378
  jump reset_state
379
 
380
 
381
// %e, %f, %g: Print floating point number
382
specif_float:
383
    //jump specif_float1               // (intermediate jump target specif_float placed here to avoid overflow in call table)
384
 
385
    // float not implemented. print as %#LX
386
    int r11 |= 0x30                    // print 0x prefix, 64 bits
387
    jump specif_hex
388
 
389
 
390
// reference point, default in call table, print unknown character:
391
def:                                   // default, reference point in call table
392
unknown_character:                     // unknown character after '%'
393
  call r10                             // print character
394
  //jump reset_state
395
reset_state:                           // reset state after '%' command
396
  int r11 = 0                          // reset modifiers
397
  int r12 = 0                          // state start
398
  int r13 = 0                          // reset field width
399
  return
400
 
401
 
402
// %x: Print hexadecimal
403
specif_hex:                            // X: hexadecimal
404
  int r7 = r8 & 0x20                   // is lower case
405
  int64 r4 = [r3]                      // read integer from parameter list
406
  int64 r3 += 8                        // increment parameter list
407
  if (int !(r11 & 0x20)) {             // check if long int
408
    int32 r4 = r4                      // not long. truncate to 32 bits
409
  }
410
specif_hex2:                           // entry from %i (decimal) if number too big
411
  int64 r5 = bitscan(r4, 1)            // find number of bits
412
  uint32 r5 >>= 2
413
  int32 r5++                           // number of digits to print
414
  int r13 -= r5                        // number of leading or trailing spaces to print
415
  int r6 = test_bit(r11, 4)            // '#' option
416
  int r13 -= 2, mask = r6              // make space of 0x prefix
417
 
418
  if (int !(r11 & 1)) {                // field is right justified. print leading spaces
419
    int r8 = ' '                       // leading spaces
420
    int r6 = test_bit(r11, 1)          // get bit 1: leading zeroes
421
    int r8 = '0', mask=r6, fallback=r8 // leading zeroes instead of leading spaces
422
    while (int r13 > 0) {              // print r13 leading spaces or zeroes
423
      call r10
424
      int r13--
425
    }
426
  }
427
 
428
  if (int r11 & 0x10) {                // '#' flag. Print 0x prefix
429
    int r8 = '0'
430
    call r10
431
    int r8 = 'X' | r7                  // 'x' or 'X'
432
    call r10
433
  }
434
 
435
  // convert to hexadecimal
436
  if (int r5 > 8) {                    // must use 64 bits
437
      int r6 = 16 - r5                 // number of digits to skip
438
      int r6 <<= 2                     // number of bits to skip
439
      uint64 r4 <<= r6                 // remove leading zero bits
440
      for (int ; r5 > 0; r5--) {       // loop for r5 digits
441
          uint64 r4 = rotate(r4, 4)    // get digit into low position
442
          int r8 = r4 & 0xF            // get digit
443
          int r8 += '0'                // convert to ASCII
444
          int r6 = r8 > '9'            // digit is A - F
445
          int r8 += 7, mask = r6       // add 7 to get letter A - F
446
          int r8 |= r7                 // lower case
447
          call r10                     // print character
448
      }
449
  }
450
  else {   // use 32 bits. CPU may not support 64 bits
451
      int r6 = 8 - r5                  // number of digits to skip
452
      int r6 <<= 2                     // number of bits to skip
453
      uint32 r4 <<= r6                 // remove leading zero bits
454
      for (int ; r5 > 0; r5--) {       // loop for r5 digits
455
          uint32 r4 = rotate(r4, 4)    // get digit into low position
456
          int r8 = r4 & 0xF            // get digit
457
          int r8 += '0'                // convert to ASCII
458
          int r6 = r8 > '9'            // digit is A - F
459
          int r8 += 7,  mask = r6      // add 7 to get letter A - F
460
          int r8 |= r7                 // lower case
461
          call r10                     // print character
462
      }
463
  }
464
  // print any trailing spaces
465
  int r8 = ' '                         // trailing spaces
466
  while (int r13 > 0) {                // print r13 trailing spaces
467
    call r10
468
    int r13--
469
  }
470
  jump reset_state
471
 
472
 
473
// %i, %d: Print signed decimal integer
474
specif_dec:                            // i: signed decimal
475
  int64 r4 = [r3]                      // read integer from parameter list
476
  int64 r3 += 8                        // increment parameter list
477
  if (int r11 & 0x20) {                // %li: 64-bit integer
478
    int64 r5 = test_bit(r4, 63)        // get sign bit
479
    int64 r4 = -r4, mask = r5          // change sign if negative
480
    int r11 |= 0x200, mask = r5        // set bit to remember negative
481
    int64 r6 = bitscan(r4, 1)          // find number of bits
482
    if (int r6 > 31) {                 // cannot handle 64 bits decimal. Do hexadecimal instead
483
      int r11 |= 0x11                  // prepare for hexadecimal escape. get 0x prefix and left justify
484
      int r7 = 0                       // use upper case for hexadecimal escape
485
      if (int8+ r5 & 1) {
486
        int r8 = '-'                   // print '-'
487
        call r10
488
      }
489
      jump specif_hex2                 // print as hexadecimal
490
    }
491
  }
492
  else {
493
    if (int r11 & 0x80) {              // %hhi: int8
494
      int32 r5 = test_bit(r4, 7)       // get sign bit
495
      int8 r4 = -r4, mask = r5         // change sign if negative. truncate to 8 bits
496
      int r11 |= 0x200, mask = r5      // set bit to remember negative
497
    }
498
    else {
499
      if (int r11 & 0x40) {            // %hhi: int16
500
        int32 r5 = test_bit(r4, 15)    // get sign bit
501
        int16 r4 = -r4, mask = r5      // change sign if negative. truncate to 16 bits
502
        int r11 |= 0x200, mask = r5    // set bit to remember negative
503
      }
504
      else {
505
        // %i: int32
506
        int32 r5 = test_bit(r4, 31)    // get sign bit
507
        int32 r4 = -r4, mask = r5      // change sign if negative. truncate to 16 bits
508
        int r11 |= 0x200, mask = r5    // set bit to remember negative
509
      }
510
    }
511
  }
512
  jump specif_uns2                     // sign has been stored in r11. continue in unsigned
513
 
514
 
515
// %u: Print unsigned decimal integer
516
specif_uns:                           // u: unsigned decimal
517
  int64 r4 = [r3]                      // read integer from parameter list
518
  int64 r3 += 8                        // increment parameter list
519
  if (int r11 & 0x20) {                // %li: 64-bit integer
520
    int64 r6 = bitscan(r4, 1)          // find number of bits
521
    int r8 |= 0x10                     // prepare for hexadecimal escape. get 0x prefix
522
    int r7 = 0                         // use upper case for hexadecimal escape
523
    if (int r6 > 31) {jump specif_hex2}// cannot handle 64 bits decimal. Do hexadecimal instead
524
  }
525
 
526
specif_uns2:
527
  int64 sp -= 8                        // save r14
528
  int64 [sp] = r14
529
 
530
  // 32 bit decimal signed or unsigned
531
  // First two BCD digits are made with simple subtraction to avoid the need for a larger bit field
532
  int r5 = 0                           // upper two BCD digits
533
 
534
  while (uint32 r4 >= 1000000000) {
535
  nop
536
    uint32 r4 -= 1000000000
537
    uint32 r5 += 0x10
538
    nop
539
  }
540
  while (uint32 r4 >= 100000000) {
541
    uint32 r4 -= 100000000
542
    uint32 r5 += 0x01
543
  }
544
 
545
  // Generate 8 BCD digits using double dabble algorithm
546
  int32 r14 = 0                        // generate BCD in r14
547
  for (int r6 = 0; r6 < 32; r6++) {    // loop for 32 bits
548
      int32 r7 = r14 + 0x33333333      // digit values 5-9 will set bit 3 in each 4-bit nibble
549
      int32 r7 &= 0x88888888           // isolate bit 3 in each nibble
550
      int32 r8 = r7 >> 3               // generate value 3 in nibbles with value 5-9
551
      int32 r7 >>= 2
552
      int32 r7 |= r8                   // this will have 3 for each nibble with a value 5-9
553
      int32 r14 += r7                  // add 3 to nibble values 5-9 to generate 8-12
554
      int32 r14 = funnel_shift(r4, r14, 31)  // shift most significant bit of r4 into r14
555
      int32 r4 <<= 1
556
  }
557
  // r5:r14 = BCD value
558
 
559
  // determine width
560
  int r6 = bitscan(r14, 1)             // number of significant bits
561
  uint r6 >>= 2                        // number of significant digits in low part
562
  int r6++                             // number of digits in low part
563
  if (int r5 != 0) {                   // high part is nonzero
564
    int r6 = bitscan(r5, 1)            // find number of digits in high part
565
    uint r6 >>= 2
566
    int r6 += 9                        // number of digits total
567
  }
568
  int r7 = test_bits_or(r11, 0x20C)    // leading sign needed
569
  int r6 += r7                         // number of characters needed
570
  int r13 -= r6                        // number of leading or trailing spaces needed
571
 
572
  if (int !(r11 & 1)) {                // right justified
573
    int r6 = r13 > 0 && r7             // leading sign && leading spaces
574
    int r4 = test_bit(r11, 1), options=1, fallback=r6 // leading zeroes and leading sign. sign must come first
575
    int r8 = ' '                       // leading sign to print
576
    int r6 = test_bit(r11, 2)          // flag for '+' prefix
577
    int r8 = '+', mask=r6, fallback=r8 // leading + required if not negative
578
    int r6 = test_bit(r11, 9)          // flag for negative
579
    int r8 = '-', mask=r6, fallback=r8 // leading -. value is negative
580
    if (int r4 & 1) {                  // sign must come before leading zeroes
581
      call r10                         // print leading sign
582
      int r7 = 0                       // remember leading sign has been written
583
    }
584
    // print leading spaces or zeroes
585
    int r8 = ' '                       // space
586
    int r6 = test_bit(r11, 1)          // flag for leading zeroes
587
    int r8 = '0', mask=r6, fallback=r8
588
    while (int r13 > 0) {              // write leading spaces or zeroes
589
      call r10
590
      int r13--
591
    }
592
  }
593
  if (int r7 & 1) {                  // sign after leading spaces
594
    int r8 = ' '                     // space
595
    int r6 = test_bit(r11, 2)        // flag for '+' prefix
596
    int r8 = '+', mask=r6, fallback=r8 // leading + required if not negative
597
    int r6 = test_bit(r11, 9)        // flag for negative
598
    int r8 = '-', mask=r6, fallback=r8 // leading -. value is negative
599
    call r10                         // write sign
600
  }
601
 
602
  int r4 = 0                           // remember if first digit has been printed
603
 
604
  // print high two digits
605
  uint32 r5 <<= 24                     // left justify high part
606
  for (int r6 = 2; r6 > 0; r6--) {     // print two high digits if any
607
      int32 r5 = rotate(r5, 4)         // get most significant digit first
608
      int8 r8 = r5 & 0x0F
609
      int r4 = (r8 != 0) || r4         // digit has been printed
610
      int8 r8 += '0'                   // convert to ASCII
611
      if (int r4 != 0) {
612
          call r10                     // print character to stdout
613
      }
614
  }
615
 
616
  // print low 8 decimal digits
617
  for (int r6 = 8; r6 > 0; r6--) {
618
      int32 r14 = rotate(r14, 4)       // get most significant digit first
619
      int8 r8 = r14 & 0x0F
620
      int r4 = (r8 != 0) || r4         // digit has been printed
621
      int r4 = (r6 == 1) || r4         // last digit must be printed
622
      int8 r8 += '0'                   // convert to ASCII
623
      if (int r4 != 0) {
624
          call r10                     // print character to stdout
625
      }
626
  }
627
 
628
  // print trailing spaces
629
  int r8 = ' '                         // space
630
  while (int r13 > 0) {                // write trailing spaces
631
    call r10
632
    int r13--
633
  }
634
 
635
  int64 r14 = [sp]                     // restore r14
636
  int64 sp += 8
637
 
638
  jump reset_state                     // finished
639
 
640
 
641
  // %e, %f, %g: Print floating point number. not implemented
642
specif_float1:
643
  nop
644
  jump reset_state                     // finished
645
 
646
code end

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.