Page 2 of 2
Re: Getting code size even smaller
Posted: Mon Jan 11, 2016 6:28 am
by barrym95838
... I'm sure that much greater optimizations can be achieved but that would take a lot of further research and I already have something that works a treat ...
I stewed for many hours cooking the
UM/MOD and
UD/MOD further down in that thread. I don't have a 6502 Forth handy to do the speed comparison, but I'm willing to bet you a soda pop that mine will beat yours slightly for speed and significantly for size.
Mike B.
Re: Getting code size even smaller
Posted: Mon Jan 11, 2016 6:50 am
by teamtempest
Since you don't use the X or Y registers in the main loops, you might consider saving the length value in them. Updating is quicker and shorter; you can also do it before updating the pointers so as not to waste time doing that if it's not necessary (not a big deal overall, more of a neatness thing). You'll have to put the length values in those registers, which is an opportunity to check if the initial value is zero:
Code: Select all
; initialize length
; - Z-flag set if no length, clear if at least one byte
INI_LEN:
ldx lenl
ldy lenh
bne +
txa
+ rts
; update length, source and target pointers
; - Z-flag set if done, clear if not done
UPD_STL:
txa ; update length
bne +
tya
beq done ; no more to do
dey
+ dex
inc srcl ; update source pointer
bne +
inc srch
+ inc tgtl ; update target pointer
bne done
inc tgth ; warning: sets Z-flag if rollover from $FFFF to $0000
done:
rts
If you didn't want to disturb the A register in these routines, you could replace all the "t-a" instructions with "cp- #$00". Adds three bytes overall but no time.
Re: Getting code size even smaller
Posted: Mon Jan 11, 2016 8:47 am
by theGSman
I stewed for many hours cooking the
UM/MOD and
UD/MOD further down in that thread. I don't have a 6502 Forth handy to do the speed comparison, but I'm willing to bet you a soda pop that mine will beat yours slightly for speed and significantly for size.
You'd win that bet hands down. At the time I dreamed up the algorithm and method of achieving it, I'd never heard of the concept of gradually shifting the dividend out and the quotient/remainder in.
I will definitely have to examine your code in more detail some time.
Re: Getting code size even smaller
Posted: Mon Jan 11, 2016 11:38 am
by floobydust
I've updated the UPD_STL routine and it's now 21 bytes in size, a savings of 5 bytes.
Code: Select all
UPD_STL INC SRCL ;Increment source low byte
BNE UPD_TL ;Check for rollover
INC SRCH ;Increment source high byte
UPD_TL INC TGTL ;Increment target low byte
BNE DECLEN ;Check for rollover
INC TGTH ;Increment target high byte
;
;DECLEN subroutine: decrement 16-bit variable LENL/LENH
DECLEN LDA LENL ;Get length low byte
BNE SKP_LENH ;Test for LENL = zero
DEC LENH ;Else decrement length high byte
SKP_LENH DEC LENL ;Decrement length low byte
RTS ;Return to caller
The memory move and memory fill routines have the stayed the same at 15 bytes each. I rewrote the compare routine so it handles the EEPROM writing based on a flag setting. It no longer requires the JSR/RTS to the error routine which prints the failed address. This resulted in the compare routine being 9 bytes larger.
Code: Select all
COMPLP LDA LENL ;Get low byte of length
ORA LENH ;OR in High byte of length
BEQ QUITMV ;If zero, nothing to write
BIT TEMP2 ;Check for EEPROM programming
BPL SKP_BURN ;If bit 7 not set, skip it
JSR BURN_BYTE ;Else Burn a byte to EEPROM
SKP_BURN LDA (SRCL) ;Else load source
CMP (TGTL) ;Compare to source
BEQ CMP_OK ;If compare is good, continue
;
LDA TEMP2 ;Get EEPROM flag
ORA #$40 ;Get bit 6 mask for error
STA TEMP2 ;Store to flag to show error in EEPROM write
JSR SPC2 ;Send 2 spaces
JSR DOLLAR ;Print $ sign
LDA TGTH ;Get high byte of address
LDY TGTL ;Get Low byte of address
JSR PRWORD ;Print word
JSR SPC ;Add 1 space for formatting
;
CMP_OK JSR UPD_STL ;Update pointers
BRA COMPLP ;Loop back until done
The EEPROM write routine was rewritten to simply set the flag, call the compare routine and check the flag for an error on return to print the appropriate message before exiting. This saved 20 bytes of code.
Code: Select all
PROG LDA #$80 ;Get EEPROM write active mask
STA TEMP2 ;Set flag for COMPLP routine
JSR COMPLP ;Call routine to write/compare
;
BIT TEMP2 ;Check for error bit in flag
BVC PRG_GOOD ;Branch if no errors
;
LDA #$26 ;Get Prog failed message
BRA BRA_PRMPT ;Branch to Prompt routine
;
PRG_GOOD LDA #$25 ;Get completed message
JSR PROMPT ;Send to console and exit
LDA #$27 ;Get warning message for RTC and Reset
BRA_PRMPT JMP PROMPT ;Send to console and exit
Since starting this thread, between the core routines here plus two others which increment and decrement another 16-bit pointer, I've reduced code by 27 bytes. I'm still looking at some other options and can likely save a few more bytes by putting the length check for zero in the UPD_STL routine, but it needs to check on entry and confirm on exit to work with the existing routines.