barrym95838 wrote:
Well, I'm kinda thinking that I would want AND, OR, EOR, LSR, BRL, BSL, ROL, ROR, MUL, DIV, MOD, and a way to more gracefully call a 6502 subroutine without having to always do something like 'RTN : LDA $00 : LDX $02 : LDY $04 : JSR Native : STA $00 : STX $02 : STY $04 : JSR Sweet16'. A new instruction (call it 'J02' or something) could be just three bytes long and would do all of that for you. If I could get all of that at the cost of losing half of my registers, I would be tempted to do so.
Mike
Adding code to Sweet16 is kind of a toughie, but it's doable. For general purpose operators, I'd flag it with one of the single-byte opcodes ($0x) followed by a second opcode with a register, e.g. ANDD R3 (for AND double) would be $0e $13, and ORD R10 (OR double) would be $0e $2a. I didn't need to do that, but I managed to shrink my (FIND) word down by 31 bytes and it's still pretty peppy. I haven't benchmarked it yet vs. a real Forth
Code:
33 bytes (wordlen16 and strcomp16 6502)
>C:0635 84 17 a0 02 b1 0a 29 3f 85 16 60 a4 0c c8 c8 b1 ......)?..`.....
>C:0645 0a 51 02 0a d0 07 88 c0 02 d0 f4 38 24 18 26 1d .Q.........8$.&.
>C:0655 60
55 bytes (opfind sweet16 with ext)
>C:0956 00 b0 38 21 37 0e 21 35 0d 35 06 2b 36 27 35 0d ..8!7.!5.5.+6'5.
>C:0966 35 06 26 db 02 1a 07 05 0d 40 06 03 03 65 01 ee 5.&......@...e..
>C:0976 65 25 a6 31 e1 45 b6 15 80 00 f8 d5 06 02 e8 e8 e%.1.E..........
>C:0986 0f 28 31 00 4c 80 00
88 bytes totatl
Originally was all 6502
Code:
119 bytes
>C:09a6 a0 01 20 1f 07 84 0f a0 02 b1 0a 29 1f 85 0c b1 .. ........)....
>C:09b6 02 85 0e 29 1f 85 0d a5 0c c5 0d 90 43 d0 31 a5 ...)........C.1.
>C:09c6 0e 29 20 d0 2b a5 0d 69 01 a8 b1 02 51 0a 0a d0 .) .+..i....Q...
>C:09d6 1f 88 c0 02 d0 f4 a4 0d c8 c8 98 65 02 85 02 a4 ...........e....
>C:09e6 03 90 01 c8 84 03 a5 0e 0a 0a b0 23 c6 0f 90 1f ...........#....
>C:09f6 a0 00 b1 02 48 c8 b1 02 85 03 68 85 02 c8 d0 af ....H.....h.....
>C:0a06 a5 0b 85 03 a5 0a 69 02 85 02 90 03 e6 03 18 a4 ......i.........
>C:0a16 0f 98 69 00 4c f5 08
and this is what the source looks like, at the end of my sweet16.a65 file
Code:
.BYT <BS-1 ;C
.BYT <INR-1 ;EX
.BYT <EXT-1 ;D
.BYT <DCR-1 ;FX
.BYT <PULL-1 ;E
.BYT 0 ;UNUSED
.BYT <PUSH-1 ;F
...
BK RTS
RS JMP RSZ
RTN JMP RTNZ
EXT LDA #R11 ; SETZ will use R11 for the indirect transfer
STA R14H
ASL
TAX
LDY #1 ; point to high byte of transfer address
JSR SETZ
JMP (r11) ; implement your 6502 extension to Sweet16 here!
PULL BPL PULLZ ; bra
PUSH JSR getpstack ; get PETTIL stack pointer
...
; returns just the low 6 bits of a length byte
;inputs
; N0 (R5) = address
;returns
; R11 = low bits of length byte at (N0+2)
wordlen16 sty r11+1 ; clear high byte
ldy #2
lda (n),y
and #$3f
sta r11 ; R11 = length
rts
;inputs
; TOS (R1) = addr-2 of a counted string
; N0 (R5) = current LFA in the dictionary chain (initially the last LFA)
; R7 = length of words
;returns
; C = true if the strings match
strcomp16 ldy n+2 ; the length
iny
iny
strcomp16a lda (n),y
eor (tos),y
asl ; ignore bit7
bne strcomp16b ; different? outtie fail
dey
cpy #2
bne strcomp16a ; C flag is set on successful strcmp
sec ; success!
.byt $24 ; BIT zp instruction
strcomp16b clc ; fail
rol R14H ; tell Sweet16 about the C flag
rts
and how it's invoked from the main program
Code:
;--------------------------------------------------------------
;
; (FIND) ( name-2 LFA -- name-2 0 | CFA flag )
;
; * outer interpreter headerless
;
; name-2 is the address-2 of a counted string we are searching for.
; LFA is the LFA at the head of a chain of LFAs
; returns
; ( CFA -1 ) if found normal word
; ( CFA 1 ) if found immediate word
; ( name 0 ) if not found
;
;pfindlfa .byt $de,$ad
; .byt (pfind-*-1)|bit7
; .asc "(FIND",")"|bit7
opfind brk
.byt sub | R0
.byt st | N3
.byt ld | TOS
.byt st | N2
.byt pull
.byt ld | TOS
.byt st | N0
.byt ext
.word wordlen16
.byt ld | R11 ; set search length
.byt st | N1
.byt ld | N2
opfind02 .byt st | N0
.byt ext
.word wordlen16
.byt ld | N1 ; search length
.byt cpr | R11 ; dict length
.byt bnc , <(opfind06-*-2) ; we went past it. outtie
.byt bnz , <(opfind03-*-2) ; different lengths, skip
.byt ext
.word strcomp16
.byt bc , <(opfind04-*-2)
opfind03 .byt ldd | N0 ; hop
.byt br , <(opfind02-*-2)
opfind04 ;winner!
.byt ldd | N0 ; add 2 to the LFA
.byt ld | N0 ; now it's an NFA
.byt add | N1 ; add the length
.byt st | TOS ; now it's almost a CFA
.byt inr | TOS ; add 1, now it's a CFA
.byt ldi | N0 ; fetch dictionary length byte
.byt sub | N1 ; subtract clean length leaving only bits
.byt set | N0
.word $80
.byt dcr | N3 ; assume it's a normal word
.byt cpr | N0
.byt bz , <(opfind06-*-2)
.byt inr | N3
.byt inr | N3
opfind06 .byt push
.byt ld | N3
.byt st | TOS
.byt rtn
jmp next