// SCANTERM     Demonstrate I/O for terminal

// This program does lexical analysis by finding the
// separate words on an input line. It counts words and
// characters within words. (Stop it with CTRL/C.)
        IBUFL   = 256             // Input allowance
        SPACE   = 0x20            // ASCII code for 
        .global gets, puts, printf
        .data                     // Declare storage
        .align  8                 // Desired alignment
IBUF:   .skip   IBUFL             // Input line
PRMT:   stringz "Enter a line of text (CTRL/C to quit)"
TELL:   stringz "Found %d words containing %d characters.\n"
         .text                    // Section for code
        .align  32                // Desired alignment
        .global main              // These three lines
        .proc   main              //  mark the mandatory
main:                             //   'main' program entry
        .prologue 12,r32          // Mask for rp, ar.pfs only
        alloc   loc0 = ar.pfs,0,3,3,0  // ins, locals, outs
        .save   rp,loc1           // Must save return address
        mov     loc1 = b0;;       //  to our caller
        .body
        mov     loc2 = gp         // Save gp
line:   add     out0 = @gprel(PRMT),gp  // out0 -> prompt
        br.call.sptk.many b0 = puts  // Unformatted output
        mov     gp = loc2         // Restore gp
        cmp4.lt p6,p0 = ret0,r0   // If any error,
   (p6) br.cond.sptk.few stop0;;  //  go to handler (null)
        add     out0 = @gprel(IBUF),gp  // out0 -> buffer
        br.call.sptk.many b0 = gets  // Unformatted input
        mov     gp = loc2         // Restore gp
        cmp.eq p6,p0 = ret0,r0    // If any error,
   (p6) br.cond.sptk.few stop1;;  //  go to handler (null)
first:  mov     r20 = 0           // Gr20 = character count
        mov     r21 = 0           // Gr21 = word count
        addl	r14 = @gprel(IBUF),gp;; // Gr14 --> input
next:   ld1     r22 = [r14],1;;   // Get a character; bump
        cmp.eq  p7,p8 = SPACE,r22 // End of word?
        cmp.eq  p6,p0 = 0x0,r22   //  NUL marks end
   (p6) br.cond.spnt.few nomore;; //   of our work here
   (p8) add     r20 = 0x1,r20     // No: count a character
   (p7) add     r21 = 0x1,r21     // Yes: count a word
        br.cond.sptk.few next     // Go back for more
nomore: add     r21 = 0x1,r21     // The last word
        add     out0 = @gprel(TELL),gp;;  // out0 -> format
        mov     out1 = r21        // out1 = number of words
        mov     out2 = r20        // out2 = number of chars
        br.call.sptk.many b0 = printf  // C print function
        mov     gp = loc2         // Restore gp
        cmp4.lt p6,p0 = ret0,r0   // If any error,
   (p6) br.cond.sptk.few stop0    //  go to handler (null)
        br.cond.sptk.many line    // Look for another line?
stop0:                            // Output error
stop1:                            // EOF or input error
done:   mov     ret0 = 0          // Signal all is normal
        mov     b0 = loc1         // Restore return address
        mov     ar.pfs = loc0     // Restore caller's ar.pfs
        br.ret.sptk.many b0;;     // Back to command line
        .endp   main              // Mark end of procedure