石原 博の覚書

電子工作に関する日々の覚書を記載します

デジットのジャンクの68KボードForthでSDカードアクセス

2023-08-06 09:43:23 | 日記
「SDカードをDISK代わりにしたForth 2023-07-18」でZ80でのSDカードアクセスが出来たので
「デジットのジャンクの68KボードでForthを動かす 2022-02-23」で動作したForthでSDカードを使用出来るようにした。

その際にいくつかの問題が発生したので覚書

注意点1
 QSTACKが変
 : ?STACK ( -- ) S0 @ DUP SP@ < 1 ?ERROR $100 + SP@ < 7 ?ERROR ;
 要するに「S0 @」(スタックの初期値) と 「SP@」(現スタック) を比較している。
 スタックは減少方向に伸びるので、初期値より現スタックが大きければPOPしすぎてUnderflowしているということ。
 ところがこの定義ではDUP操作してから SP@ しているので辻褄が合わなくなっている。 またOverflow側は明らかにおかしい。
 
 他のForthソースを調べて見ると
 F83では
 : ?STACK ( -- ) SP@ SP0 @ SWAP U< ABORT" Stack Underflow" SP@ PAD U< ABORT" Stack Overflow" ;
 最初なぜわざわざ「SP@」から取得しSWAPしているのかわからなかったけれど、作業で変動する前の現スタックを取得している。
 またPUSH側はPADにぶつからなければOK(メモリマップ的に正常なら PAD<SP@)
 
 ちなみに8080Forthや 8086Forthでは
 : ?STACK ( -- ) SP@ SP0 @ SWAP U< 1 ?ERROR SP@ HERE 80H + U< 7 ?ERROR ;
なのでF83と同じ(PUSH側はHEREと128バイトの余裕を見ている)

さらにPDP11 Forthでは
: ?STACK ( -- ) S0 @ 2 - SP@ U< 1 ?ERROR SP@ HERE 200 + U< 2 ?ERROR ;
 なので先に「SP@」してはいないが、「2 -」 で補正している。
 
 また6800 Forthでは
 : ?STACK ( -- ) $12 PORIG @ 2 - SP@ < 1 ?ERROR SP@ HERE $80 + < IF 2 ?ERROR THEN ;

 これらから考えて、間違っているんだろうなあ。仕方ないので
 : ?STACK ( -- ) SP@ S0 @ SWAP < 1 ?ERROR SP@ S0 @ $180 - < 7 ?ERROR ;
とした。(メモリマップ参照 スタックは BUFE〜INITS0にないと行けない)
 
 (参考)メモリマップ
 -------------------------------------
 1000 BM(BOTTOM OF MEMORY)
DISK BUFFER(Screan * 2 + alpha)
 1810 BUFE
USER STACKAREA(USS $1E0)
 19EE INITS0
RETURN STACKAREA(RTS $200)
 1BEE INITR0
 1BF0 IOARE
I/O routine
 2000 DP0
Dictionary
 3720 INITDP
USER Dictionary
 7F00 EM
 
 
注意点2
上記でも U< ではなく、< を使用しているとおり、符号なしの比較がForthのソースではコメントアウトされている。
なので0x8000以降には置くためにはいろいろ変更が必要
 
注意点3
 EDITORがない。まあForthで書かれたLineEditorがWeb上にある
 (http://forth.org/OffeteStore/1010_SystemsGuideToFigForth.pdf) ので、入れようとした。
 ところが 不足WORDあり 「FLUSH」とか「1-」 とか。まあこれも定義すればよい

注意点4
 Web上の「1010_SystemsGuideToFigForth.pdf」のEDITORを導入するといくつかの不具合が見つかったので以下対応を行った
 ・ワードTEXTの定義でワードWORDを使用しているが、返り値があることを期待している -> Forth79では返り値があった? HEREを入れて対応
 ・0EHなど16進数を使用している。10進数に直しても良いが前後をHEXとDECIMALではさみ対応
 ・定義順がおかしい。例えばコマンドSやコマンドDの定義で、直後に定義しているコマンドEを使用している
  (これは説明の順番の問題かもしれない)
 ・ワードSで、DO +LOOPを使用している。 1 +LOOPとなっているが、コメントを見る限り -1 +LOOPとする必要がある。
  ただし、使用した68KForthでは +LOOPがマイナスの増分に対応してない。+LOOP側を修正することも出来るが、今回はワードS側の定義を変更
 ・ワード DELETEで、ワードMOVEを使用している。CMOVEの間違いか?
 
注意点5(2023/8/10追記)
 エディタのコマンド Pに癖がある。 行番号 P 文字列 として書き込む場合、空行とするため、行番号 P[改行] とP直後に改行すると、
 0(null)が書き込まれる。Forth的にはnullでブロック終了なので、LOADしてもそこで終了する。画面上nullも空白もわからないので悩んだ。
 P直後に空白を入れるなり、行番号 Eで消せば良いのだけど。

===注意点3,4に対応したエディタ===
: 1- 1 - ;
: FLUSH 5 0 DO 0 BUFFER DROP LOOP ;

VOCABULARY EDITOR IMMEDIATE
EDITOR DEFINITIONS

: TEXT ( c -- )
HERE
C/L 1+ BLANKS
WORD
HERE PAD
C/L 1+ CMOVE
;

: LINE ( n -- addr )
DUP [ HEX ] FFF0 [ DECIMAL ] AND
17 ?ERROR
SCR @
(LINE)
DROP
;

: -MOVE ( addr n -- )
LINE
C/L CMOVE
UPDATE
;

: H ( n -- )
LINE
PAD 1+
C/L DUP PAD C!
CMOVE
;

: E ( n -- )
LINE
C/L BLANKS
UPDATE
;

: S ( n -- )
DUP 15 SWAP - 0
DO
14 I - DUP LINE SWAP 1+
-MOVE
LOOP
E
;


: D ( n -- )
DUP H
[ HEX ] 0F [ DECIMAL ]
DUP ROT
DO
I 1+ LINE
I -MOVE
LOOP
E
;

: R ( n -- )
PAD 1+
SWAP -MOVE
;

: P ( n -- )
1 TEXT
R
;

: I ( n -- )
DUP S
R
;

: CLEAR ( n -- )
SCR !
[ HEX ] 10 [ DECIMAL ] 0 DO
FORTH I
EDITOR E
LOOP
;

: COPY ( n1 n2 -- )
B/SCR *
OFFSET @ +
SWAP B/SCR *
B/SCR OVER +
SWAP DO
DUP
FORTH I
BLOCK
2 - !
1+
UPDATE
LOOP
DROP
FLUSH
;

: 2DROP ( d -- )
DROP DROP ;

: 2DUP ( d -- d d )
OVER OVER ;

: 2SWAP ( d1 d2 -- d2 d1 )
ROT >R
ROT R>
;

: -TEXT ( addr1 n addr2 -- f )
SWAP -DUP
IF
OVER + SWAP
DO
DUP C@
FORTH I C@ -
IF 0= LEAVE
ELSE 1+ THEN
LOOP
ELSE DROP 0=
THEN
;

: MATCH ( addr1 n1 addr2 n2 -- f n3 )
>R >R 2DUP
R> R> 2SWAP
OVER + SWAP
DO
2DUP
FORTH I
-TEXT
IF
>R 2DROP R>
- I SWAP -
0 SWAP
0 0 LEAVE
THEN
LOOP
2DROP
SWAP 0= SWAP
;

: TOP ( -- )
0 R# !
;

: #LOCATE ( -- n1 n2 )
R# @
C/L /MOD
;

: #LEAD ( -- addr n )
#LOCATE
LINE
SWAP
;

: #LAG ( -- addr n )
#LEAD
DUP >R
+
C/L R> -
;

: M ( n -- )
R# +!
CR SPACE
#LEAD TYPE
[ HEX ] 5F [ DECIMAL ] EMIT
#LAG TYPE
#LOCATE .
;

: T ( n -- )
DUP C/L *
R# !
H
0 M
;

: L ( -- )
SCR @ LIST
0 M
;

: 1LINE ( -- f )
#LAG PAD COUNT
MATCH
R# +!
;

: FIND ( -- )
BEGIN
[ HEX ] 3FF [ DECIMAL ] R# @ <
IF
TOP
PAD HERE
C/L 1+ CMOVE
0 ERROR
ENDIF
1LINE
UNTIL
;

: DELETE ( n -- )
>R
#LAG +
FORTH R -
#LAG
R MINUS R# +!
#LEAD +
SWAP CMOVE
R> BLANKS
UPDATE
;

: N ( -- )
FIND
0 M
;

: F ( -- )
1 TEXT
N
;

: B ( -- )
PAD C@
MINUS M
;

: X ( -- )
1 TEXT
FIND
PAD C@
DELETE
0 M
;

: TILL ( -- )
#LEAD +
1 TEXT
1LINE
0= 0 ?ERROR
#LEAD + SWAP -
DELETE
0 M
;

: C ( -- )
1 TEXT PAD COUNT
#LAG ROT OVER MIN >R
FORTH R
R# +!
R - >R
DUP HERE R CMOVE
HERE #LEAD + R>
CMOVE
R> CMOVE
UPDATE
0 M
;