From 79396d8acdba71d9d5e2ce52a906cb19faa67775 Mon Sep 17 00:00:00 2001
From: cuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Date: Sat, 23 Nov 2002 22:51:25 +0000
Subject: [PATCH] Rewrote fwrite in assembler

git-svn-id: svn://svn.cc65.org/cc65/trunk@1614 b7a2c559-68d2-44c3-8de9-860c34a00d81
---
 libsrc/common/.cvsignore |   1 -
 libsrc/common/Makefile   |   2 +-
 libsrc/common/fwrite.c   |  51 ----------------
 libsrc/common/fwrite.s   | 129 +++++++++++++++++++++++++++++++++++++++
 libsrc/common/vfprintf.s |   3 +-
 5 files changed, 131 insertions(+), 55 deletions(-)
 delete mode 100644 libsrc/common/fwrite.c
 create mode 100644 libsrc/common/fwrite.s

diff --git a/libsrc/common/.cvsignore b/libsrc/common/.cvsignore
index 3f648ea4f..c77b59e04 100644
--- a/libsrc/common/.cvsignore
+++ b/libsrc/common/.cvsignore
@@ -18,7 +18,6 @@ freopen.s
 fseek.s
 fsetpos.s
 ftell.s
-fwrite.s
 getchar.s
 gets.s
 gmtime.s
diff --git a/libsrc/common/Makefile b/libsrc/common/Makefile
index ba1d3b697..a4548f163 100644
--- a/libsrc/common/Makefile
+++ b/libsrc/common/Makefile
@@ -30,7 +30,6 @@ C_OBJS =	_afailed.o	\
 		fseek.o		\
 		fsetpos.o	\
 		ftell.o		\
-		fwrite.o	\
 		getchar.o	\
 		gets.o		\
                 gmtime.o        \
@@ -74,6 +73,7 @@ S_OBJS = 	_fdesc.o 	\
 		fopen.o		\
 		fprintf.o	\
 		free.o		\
+		fwrite.o	\
 		getcpu.o	\
 		isalnum.o	\
 		isalpha.o	\
diff --git a/libsrc/common/fwrite.c b/libsrc/common/fwrite.c
deleted file mode 100644
index a363ad362..000000000
--- a/libsrc/common/fwrite.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * fwrite.c
- *
- * Ullrich von Bassewitz, 04.06.1998
- */
-
-
-
-#include <stdio.h>
-#include <fcntl.h>
-#include <errno.h>
-#include "_file.h"
-
-
-
-size_t fwrite (const void* buf, size_t size, size_t count, FILE* f)
-{
-    int bytes;
-
-    /* Is the file open? */
-    if ((f->f_flags & _FOPEN) == 0) {
-       	_errno = EINVAL;	   	/* File not open */
-    	return 0;
-    }
-
-    /* Did we have an error */
-    if ((f->f_flags & _FERROR) != 0) {
-    	/* Cannot write to stream */
-       	return 0;
-    }
-
-    /* How many bytes to write? */
-    bytes = size * count;
-
-    if (bytes) {
-	/* Write the data. */
-       	if (write (f->f_fd, buf, bytes) == -1) {
-	    /* Write error */
-	    f->f_flags |= _FERROR;
-	    return 0;
-	}
-    }
-
-    /* Don't waste time with expensive calculations, assume the write was
-     * complete and return the count of items.
-     */
-    return count;
-}
-
-
-
diff --git a/libsrc/common/fwrite.s b/libsrc/common/fwrite.s
new file mode 100644
index 000000000..845792c77
--- /dev/null
+++ b/libsrc/common/fwrite.s
@@ -0,0 +1,129 @@
+;
+; Ullrich von Bassewitz, 22.11.2002
+;
+; size_t __fastcall__ fwrite (const void* buf, size_t size, size_t count, FILE* f);
+; /* Write to a file */
+;
+
+        .export         _fwrite
+
+        .import         _write
+        .import         pushax, incsp6, addysp, ldaxysp, pushwysp, return0
+        .import         tosumulax, tosudivax
+
+        .importzp       ptr1
+
+        .include        "errno.inc"
+        .include        "_file.inc"
+
+
+; ------------------------------------------------------------------------
+; Code
+
+.proc   _fwrite
+
+; Save f and place it into ptr1
+
+	sta	f
+	sta	ptr1
+	stx	f+1
+	stx	ptr1+1
+
+; Check if the file is open
+
+	ldy	#_FILE_f_flags
+	lda	(ptr1),y
+	and	#_FOPEN		      	; Is the file open?
+       	bne    	@L2			; Branch if yes
+
+; File not open
+
+   	lda	#EINVAL
+   	sta	__errno
+   	lda	#0
+   	sta	__errno+1
+@L1:    jsr     incsp6
+        jmp     return0
+
+; Check if the stream is in an error state
+
+@L2:	lda	(ptr1),y		; get f->f_flags again
+	and	#_FERROR
+	bne     @L1
+
+; Build the stackframe for write()
+
+        ldy     #_FILE_f_fd
+        lda     (ptr1),y
+        ldx     #$00
+        jsr     pushax                  ; f->f_fd
+
+        ldy     #9
+        jsr     pushwysp                ; buf
+
+; Stack is now: buf/size/count/f->fd/buf
+; Calculate the number of bytes to write: count * size
+
+        ldy     #7
+        jsr     pushwysp                ; count
+        ldy     #9
+        jsr     ldaxysp                 ; Get size
+        jsr     tosumulax               ; count * size -> a/x
+
+; Check if the number of bytes is zero. Don't call write in this case
+
+        cpx     #0
+        bne     @L3
+        cmp     #0
+        bne     @L3
+
+; The number of bytes to write is zero, just return count
+
+        ldy     #5
+        jsr     ldaxysp                 ; Get count
+        ldy     #10
+        jmp     addysp                  ; Drop params, return
+
+; Call write(). This will leave the original 3 params on the stack
+
+@L3:    jsr     pushax
+        jsr     _write
+
+; Check for errors in write
+
+        cpx     #$FF
+        bne     @L4
+        cmp     #$FF
+        bne     @L4
+
+; Error in write. Set the stream error flag and bail out. _oserror and/or
+; errno are already set by write().
+
+        lda     f
+        sta     ptr1
+        lda     f+1
+        sta     ptr1+1
+        ldy     #_FILE_f_fd
+        lda     (ptr1),y
+        ora     #_FERROR
+        sta     (ptr1),y
+        bne     @L1                     ; Return zero
+
+; Write was ok. Return the number of items successfully written. Since we've
+; checked for bytes == 0 above, size cannot be zero here, so the division is
+; safe.
+
+@L4:    jsr     pushax                  ; Push number of bytes written
+        ldy     #5
+        jsr     ldaxysp                 ; Get size
+        jsr     tosudivax               ; bytes / size -> a/x
+        jmp     incsp6                  ; Drop params, return
+
+.endproc
+
+; ------------------------------------------------------------------------
+; Data
+
+.bss
+f:	.res	2
+
diff --git a/libsrc/common/vfprintf.s b/libsrc/common/vfprintf.s
index ecab1bd90..0a7f3f7ec 100644
--- a/libsrc/common/vfprintf.s
+++ b/libsrc/common/vfprintf.s
@@ -61,8 +61,7 @@ out:
   	lda	(ptr1),y
   	tax
   	dey
-  	lda	(ptr1),y
-  	jsr	pushax		; Push D->ptr
+  	lda	(ptr1),y        ; Load D->ptr
   	jsr	_fwrite
        	sta	ptr2		; Save function result
 	stx	ptr2+1