1
0
mirror of https://github.com/cc65/cc65.git synced 2024-12-27 15:29:46 +00:00

a BIT of 65C02 optimisations

Use BIT immediate instead of AND when reloading A is required
afterwards.
Add an fread unit test as the optimisation touches fread.
Sprinkle a few zero page indexed while we're at it.
This commit is contained in:
Colin Leroy-Mira 2024-02-01 20:05:57 +01:00
parent 2a03e5d8c9
commit 1fab179cb4
5 changed files with 145 additions and 10 deletions

View File

@ -13,6 +13,7 @@
.import _strlower, _strlen .import _strlower, _strlen
.macpack generic .macpack generic
.macpack cpu
; ---------------------------------------------------------------------------- ; ----------------------------------------------------------------------------
; We will store variables into the register bank in the zeropage. Define ; We will store variables into the register bank in the zeropage. Define
@ -37,7 +38,11 @@ FCount = ptr2
GetFormatChar: GetFormatChar:
ldy #0 ldy #0
.if (.cpu .bitand ::CPU_ISET_65SC02)
lda (Format)
.else
lda (Format),y lda (Format),y
.endif
IncFormatPtr: IncFormatPtr:
inc Format inc Format
bne @L1 bne @L1
@ -110,7 +115,11 @@ GetIntArg:
lda (ArgList),y lda (ArgList),y
tax tax
dey dey
.if (.cpu .bitand ::CPU_ISET_65SC02)
lda (ArgList)
.else
lda (ArgList),y lda (ArgList),y
.endif
rts rts
; ---------------------------------------------------------------------------- ; ----------------------------------------------------------------------------
@ -135,9 +144,9 @@ ReadInt:
pha ; Save digit value pha ; Save digit value
lda ptr1 lda ptr1
ldx ptr1+1 ldx ptr1+1
asl ptr1 asl a
rol ptr1+1 ; * 2 rol ptr1+1 ; * 2
asl ptr1 asl a
rol ptr1+1 ; * 4, assume carry clear rol ptr1+1 ; * 4, assume carry clear
adc ptr1 adc ptr1
sta ptr1 sta ptr1
@ -265,10 +274,16 @@ Save: lda regbank,y
; Initialize the output counter in the output descriptor to zero ; Initialize the output counter in the output descriptor to zero
lda #0 lda #0
.if (.cpu .bitand ::CPU_ISET_65SC02)
sta (OutData)
ldy #$01
sta (OutData),y
.else
tay tay
sta (OutData),y sta (OutData),y
iny iny
sta (OutData),y sta (OutData),y
.endif
; Get the output function from the output descriptor and remember it ; Get the output function from the output descriptor and remember it
@ -338,7 +353,11 @@ MainLoop:
sta (sp),y sta (sp),y
dey dey
lda FCount lda FCount
.if (.cpu .bitand ::CPU_ISET_65SC02)
sta (sp)
.else
sta (sp),y sta (sp),y
.endif
jsr CallOutFunc ; Call the output function jsr CallOutFunc ; Call the output function
; We're back from out(), or we didn't call it. Check for end of string. ; We're back from out(), or we didn't call it. Check for end of string.
@ -551,10 +570,16 @@ CheckCount:
jsr GetIntArg jsr GetIntArg
sta ptr1 sta ptr1
stx ptr1+1 ; Get user supplied pointer stx ptr1+1 ; Get user supplied pointer
.if (.cpu .bitand ::CPU_ISET_65SC02)
lda (OutData) ; Low byte of OutData->ccount
sta (ptr1)
ldy #1
.else
ldy #0 ldy #0
lda (OutData),y ; Low byte of OutData->ccount lda (OutData),y ; Low byte of OutData->ccount
sta (ptr1),y sta (ptr1),y
iny iny
.endif
lda (OutData),y ; High byte of OutData->ccount lda (OutData),y ; High byte of OutData->ccount
sta (ptr1),y sta (ptr1),y
jmp MainLoop ; Done jmp MainLoop ; Done

View File

@ -12,6 +12,8 @@
.include "stdio.inc" .include "stdio.inc"
.include "_file.inc" .include "_file.inc"
.macpack cpu
_fgetc: _fgetc:
sta ptr1 sta ptr1
stx ptr1+1 stx ptr1+1
@ -20,11 +22,16 @@ _fgetc:
jsr checkferror jsr checkferror
bne ret_eof bne ret_eof
.if (.cpu .bitand ::CPU_ISET_65SC02)
bit #_FPUSHBACK ; Check for pushed back char
beq do_read
.else
tax tax
and #_FPUSHBACK ; Check for pushed back char and #_FPUSHBACK ; Check for pushed back char
beq do_read beq do_read
txa txa
.endif
and #<(~_FPUSHBACK) ; Reset flag and #<(~_FPUSHBACK) ; Reset flag
sta (ptr1),y sta (ptr1),y

View File

@ -20,6 +20,7 @@
.include "_file.inc" .include "_file.inc"
.macpack generic .macpack generic
.macpack cpu
; ------------------------------------------------------------------------ ; ------------------------------------------------------------------------
; Code ; Code
@ -47,13 +48,21 @@
ldy #_FILE::f_flags ldy #_FILE::f_flags
lda (file),y lda (file),y
.if (.cpu .bitand ::CPU_ISET_65SC02)
bit #_FOPEN ; Is the file open?
.else
and #_FOPEN ; Is the file open? and #_FOPEN ; Is the file open?
.endif
beq @L1 ; Branch if no beq @L1 ; Branch if no
; Check if the stream is in an error state ; Check if the stream is in an error state
.if (.cpu .bitand ::CPU_ISET_65SC02)
bit #_FERROR
.else
lda (file),y ; get file->f_flags again lda (file),y ; get file->f_flags again
and #_FERROR and #_FERROR
.endif
beq @L2 beq @L2
; File not open or in error state ; File not open or in error state
@ -65,11 +74,19 @@
; Remember if we have a pushed back character and reset the flag. ; Remember if we have a pushed back character and reset the flag.
@L2: tax ; X = 0 @L2: .if (.cpu .bitand ::CPU_ISET_65SC02)
ldx #$00
bit #_FPUSHBACK
.else
tax ; X = 0
lda (file),y lda (file),y
and #_FPUSHBACK and #_FPUSHBACK
.endif
beq @L3 beq @L3
.if (.not .cpu .bitand ::CPU_ISET_65SC02)
lda (file),y lda (file),y
.endif
and #<~_FPUSHBACK and #<~_FPUSHBACK
sta (file),y ; file->f_flags &= ~_FPUSHBACK; sta (file),y ; file->f_flags &= ~_FPUSHBACK;
inx ; X = 1 inx ; X = 1
@ -118,12 +135,20 @@
; Copy the buffer pointer into ptr1, and increment the pointer value passed ; Copy the buffer pointer into ptr1, and increment the pointer value passed
; to read() by one, so read() starts to store data at buf+1. ; to read() by one, so read() starts to store data at buf+1.
.if (.cpu .bitand ::CPU_ISET_65SC02)
lda (sp)
sta ptr1
add #1
sta (sp)
ldy #1
.else
ldy #0 ldy #0
lda (sp),y lda (sp),y
sta ptr1 sta ptr1
add #1 add #1
sta (sp),y sta (sp),y
iny iny
.endif
lda (sp),y lda (sp),y
sta ptr1+1 sta ptr1+1
adc #0 adc #0
@ -134,8 +159,12 @@
ldy #_FILE::f_pushback ldy #_FILE::f_pushback
lda (file),y lda (file),y
.if (.cpu .bitand ::CPU_ISET_65SC02)
sta (ptr1) ; *buf = file->f_pushback;
.else
ldy #0 ldy #0
sta (ptr1),y ; *buf = file->f_pushback; sta (ptr1),y ; *buf = file->f_pushback;
.endif
; Restore the low byte of count and decrement count by one. This may result ; Restore the low byte of count and decrement count by one. This may result
; in count being zero, so check for that. ; in count being zero, so check for that.
@ -210,4 +239,3 @@
.bss .bss
save: .res 2 save: .res 2
pb: .res 1 pb: .res 1

View File

@ -8,7 +8,7 @@
.export _fwrite .export _fwrite
.import _write .import _write
.import pushax, incsp6, addysp, ldaxysp, pushwysp, return0 .import pushax, pusha0, incsp6, addysp, ldaxysp, pushwysp, return0
.import tosumulax, tosudivax .import tosumulax, tosudivax
.importzp ptr1 .importzp ptr1
@ -16,6 +16,7 @@
.include "errno.inc" .include "errno.inc"
.include "_file.inc" .include "_file.inc"
.macpack cpu
; ------------------------------------------------------------------------ ; ------------------------------------------------------------------------
; Code ; Code
@ -33,7 +34,11 @@
ldy #_FILE::f_flags ldy #_FILE::f_flags
lda (ptr1),y lda (ptr1),y
.if (.cpu .bitand ::CPU_ISET_65SC02)
bit #_FOPEN
.else
and #_FOPEN ; Is the file open? and #_FOPEN ; Is the file open?
.endif
bne @L2 ; Branch if yes bne @L2 ; Branch if yes
; File not open ; File not open
@ -45,7 +50,9 @@
; Check if the stream is in an error state ; Check if the stream is in an error state
@L2: lda (ptr1),y ; get file->f_flags again @L2: .if (.not .cpu .bitand ::CPU_ISET_65SC02)
lda (ptr1),y ; get file->f_flags again
.endif
and #_FERROR and #_FERROR
bne @L1 bne @L1
@ -53,8 +60,7 @@
ldy #_FILE::f_fd ldy #_FILE::f_fd
lda (ptr1),y lda (ptr1),y
ldx #$00 jsr pusha0 ; file->f_fd
jsr pushax ; file->f_fd
ldy #9 ldy #9
jsr pushwysp ; buf jsr pushwysp ; buf
@ -123,4 +129,3 @@
.bss .bss
file: .res 2 file: .res 2

70
test/ref/test_fread.c Normal file
View File

@ -0,0 +1,70 @@
/*
!!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;
char buf[32];
#define INFILE "cf.in"
int main(int argc,char **argv)
{
static char outfile_path[FILENAME_MAX+1];
static int r;
sprintf(outfile_path, "%s.test.out", argv[0]);
out = fopen(outfile_path, "wb");
if (out == NULL) {
return EXIT_FAILURE;
}
if (fread(buf, 1, sizeof(buf), out) != NULL) {
printf("Error, could fread with write-only file\n");
return 1;
}
if (!ferror(out)) {
printf("Error: file pointer should be in error state\n");
}
fclose(out);
unlink(outfile_path);
in = fopen(INFILE, "rb");
if (in == NULL) {
return EXIT_FAILURE;
}
/* Test that ungetc doesn't break fread */
buf[0] = fgetc(in);
ungetc(buf[0], in);
r = fread(buf, 1, sizeof(buf), out);
if (r == 0) {
printf("Error: could not start reading.\n");
}
fwrite(buf, 1, r, stdout);
/* Finish reading file. */
while ((r = fread(buf, 1, sizeof(buf), out)) != 0)
{
fwrite(buf, 1, r, stdout);
}
if (!feof(in))
{
printf("We should have EOF!\n");
}
fclose(in);
return 0;
}