1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-01 13:41:34 +00:00
cc65/libsrc/cbm/read.s
Oliver Schmidt 0ee9b2e446 Changed run location of INIT segment.
So far the INIT segment was run from the later heap+stack. Now the INIT segment is run from the later BSS. The background is that so far the INIT segment was pretty small (from $80 to $180 bytes). But upcoming changes will increase the INIT segment in certain scenarios up to ~ $1000 bytes. So programs with very limited heap+stack might just not been able to move the INIT segment to its run location. But moving the INIT segment to the later BSS allows it to occupy the later BSS+heap+stack.

In order to allow that the constructors are _NOT_ allowed anymore to access the BSS. Rather they must use the DATA segment or the new INITBSS segment. The latter isn't cleared at any point so the constructors may use it to expose values to the main program. However they must make sure to always write the values as they are not pre-initialized.
2015-10-14 22:52:09 +02:00

155 lines
3.7 KiB
ArmAsm

;
; 2002-11-16, Ullrich von Bassewitz
; 2013-12-23, Greg King
;
; int read (int fd, void* buf, unsigned count);
;
.export _read
.constructor initstdin
.import SETLFS, OPEN, CHKIN, BASIN, CLRCH, BSOUT, READST
.import rwcommon
.import popax
.importzp ptr1, ptr2, ptr3, tmp1, tmp2, tmp3
.include "cbm.inc"
.include "errno.inc"
.include "fcntl.inc"
.include "filedes.inc"
;--------------------------------------------------------------------------
; initstdin: Open the stdin file descriptors for the keyboard
.segment "INIT"
.proc initstdin
lda #STDIN_FILENO + LFN_OFFS
ldx #CBMDEV_KBD
ldy #$FF
jsr SETLFS
jmp OPEN ; Will always succeed
.endproc
;--------------------------------------------------------------------------
; _read
.code
.proc _read
jsr rwcommon ; Pop params, check handle
bcs invalidfd ; Invalid handle
; Check if the LFN is valid and the file is open for writing
adc #LFN_OFFS ; Carry is already clear
tax
lda fdtab-LFN_OFFS,x; Get flags for this handle
tay
and #LFN_READ ; File open for writing?
beq invalidfd
; Check the EOF flag. If it is set, don't read anything
tya ; Get flags again
bmi eof
; Remember the device number.
ldy unittab-LFN_OFFS,x
sty unit
; Valid lfn. Make it the input file
jsr CHKIN
bcc @L3 ; Branch if ok
jmp __mappederrno ; Store into __oserror, map to errno, return -1
; Read the next byte
@L0: jsr BASIN
sta tmp1 ; Save the input byte
ldx unit
bne @L0_1 ; Not keyboard/screen-editor
cmp #$0D ; Is it a Carriage Return?
bne @L0_1
jsr BSOUT ; Yes, echo it (because editor didn't)
@L0_1: jsr READST ; Read the IEEE status
sta tmp3 ; Save it
and #%10111111 ; Check anything but the EOI bit
bne devnotpresent ; Assume device not present
; Store the byte just read
ldy #0
lda tmp1
sta (ptr2),y
inc ptr2
bne @L1
inc ptr2+1 ; *buf++ = A;
; Increment the byte count
@L1: inc ptr3
bne @L2
inc ptr3+1
; Get the status again and check the EOI bit
@L2: lda tmp3
and #%01000000 ; Check for EOI
bne @L4 ; Jump if end of file reached
; Decrement the count
@L3: inc ptr1
bne @L0
inc ptr1+1
bne @L0
beq done ; Branch always
; Set the EOI flag and bail out
@L4: ldx tmp2 ; Get the handle
lda #LFN_EOF
ora fdtab,x
sta fdtab,x
; Read done, close the input channel
done: jsr CLRCH
; Clear _oserror and return the number of chars read
eof: lda #0
sta __oserror
lda ptr3
ldx ptr3+1
rts
; Error entry: Device not present
devnotpresent:
lda #ENODEV
jmp __directerrno ; Sets _errno, clears _oserror, returns -1
; Error entry: The given file descriptor is not valid or not open
invalidfd:
lda #EBADF
jmp __directerrno ; Sets _errno, clears _oserror, returns -1
.endproc
;--------------------------------------------------------------------------
.bss
unit: .res 1