Skip to content

Commit

Permalink
Rewrite fputc in assembly
Browse files Browse the repository at this point in the history
-36 bytes, -12% cycles
  • Loading branch information
colinleroy committed Jan 30, 2024
1 parent b7d61ad commit ee8c8df
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 41 deletions.
41 changes: 0 additions & 41 deletions libsrc/common/fputc.c

This file was deleted.

72 changes: 72 additions & 0 deletions libsrc/common/fputc.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
;
; Colin Leroy-Mira, 2024
;
; int __fastcall__ fputc (int c, FILE* f);
;

.export _fputc
.importzp ptr1
.import _write
.import pushax, pusha0, popax, incsp2
.import pushptr1, popptr1, returnFFFF

.include "stdio.inc"
.include "_file.inc"

_fputc:
sta ptr1
stx ptr1+1

jsr popax ; Get char, as we'll have
sta c ; to return it anyway
stx c+1

ldy #_FILE::f_flags
lda (ptr1),y
tax
and #_FOPEN ; Check for file open
beq ret_eof
txa
and #(_FERROR|_FEOF); Check for error/eof
bne ret_eof

jsr pushptr1 ; Backup fp pointer

; Push _write parameters
ldy #_FILE::f_fd
lda (ptr1),y
jsr pusha0

lda #<c
ldx #>c
jsr pushax

lda #$01
ldx #$00

; Write
jsr _write

; Check for errors
cmp #$01
bne set_ferror

; Return char
lda c
ldx #$00
jmp incsp2 ; Drop fp pointer copy

ret_eof:
jmp returnFFFF

set_ferror:
jsr popptr1
lda #_FERROR
ldy #_FILE::f_flags
ora (ptr1),y
sta (ptr1),y
jmp returnFFFF

.bss

c: .res 2
39 changes: 39 additions & 0 deletions test/ref/test_fputc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
!!DESCRIPTION!! fgets test
!!LICENCE!! Public domain
*/

#include "common.h"

#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

FILE *in, *out;
int c, err;

#define INFILE "cf.in"

int main(int argc,char **argv)
{
in = fopen(INFILE, "rb");
if (in == NULL) {
return EXIT_FAILURE;
}

if (fputc(c, in) != EOF) {
printf("Error: can fputc to a file opened for reading\n");
return EXIT_FAILURE;
}
clearerr(in);

while ((c = fgetc(in)) != EOF) {
fputc(c, stdout);
}

fclose(in);
return 0;
}

0 comments on commit ee8c8df

Please sign in to comment.