prjbrook

forth85_15 compile code start

Jul 31st, 2014
270
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 39.50 KB | None | 0 0
  1. ;this is forth85_15 Tidies up forth85_14
  2. ; got compile code to work for one simple call to "two". V tricky compilation
  3. ; of rcall opcodes.
  4.  
  5. .NOLIST
  6. .include "tn85def.inc"
  7. .LIST
  8. ;.LISTMAC ;sometimes macro code gets in way of clarity in listing
  9. .MACRO header
  10. .db high(@0), low(@0), @1, @2
  11. .ENDMACRO
  12. .MACRO mypop
  13. ld @0,-y
  14. .ENDMACRO
  15. .MACRO mypush
  16. st y+, @0
  17. .ENDMACRO
  18. .MACRO mypop2
  19. mypop @0
  20. mypop @1
  21. .ENDMACRO
  22. .MACRO mypush2
  23. mypush @0
  24. mypush @1
  25. .ENDMACRO
  26. .MACRO pushx
  27. push xl
  28. push xh
  29. .ENDMACRO
  30. .MACRO popx
  31. pop xh
  32. pop xl
  33. .ENDMACRO
  34. .MACRO pushz
  35. push zl
  36. push zh
  37. .ENDMACRO
  38. .MACRO popz
  39. pop zh
  40. pop zl
  41. .ENDMACRO
  42. .MACRO mypopa ;call r16,17 the accumulator a, ditto for r18,r19 for b
  43. mypop r17
  44. mypop r16
  45. .ENDMACRO
  46. .MACRO mypopb
  47. mypop2 r19,r18
  48. .ENDMACRO
  49. .def mylatest =r2 ;r2,r3 is mylatest
  50. .def myhere =r4 ;r4,r5 is myhere. The pointer to flash copy in buf2.
  51. .def SOFPG=r6 ;start of flash page
  52. ;r6,r7 byte adr of flash page (11c0)
  53. ;r8,r9 (0012) offset when flash comes into buf2. r8 +E0 = myhere
  54. .def SECONDLETTER =r10 ;helpful for debugging
  55. .def FOUNDCOUNTER = r11 ;dealWithWord clicks this if found =1. Counts successful finds in dictionary.
  56. .def STATE = r12
  57. .def STOP = r13 ;stop interpreting line of words
  58. .def BOTTOM = r14 ;have hit the bottom of the dict and not found a match
  59. .def FOUND = r15 ;if found=1 we have a match of Ram word on dictionary
  60. ;r20 is length of word in WORD
  61. ;r21 is the flash length of word with immediate bit 8, if any, still there
  62.  
  63. .def vl = r22
  64. .def vh = r23 ; u,v,w,x,y,z are all pointers
  65. .def wl = r24 ;w=r24,25
  66. .def wh = r25
  67.  
  68. .DSEG
  69. .ORG 0x60
  70.  
  71. .equ BUF1LENGTH = 128
  72. .equ eHERE = $0010 ;eeprom adr of system varial eHere
  73. .equ eLATEST = $0012
  74.  
  75. buf1: .byte BUF1LENGTH ;input buffer. Lines max about 125
  76. buf2: .byte BUF1LENGTH ;this fits two flash buffers
  77. varSpace: .byte 64 ;might need more than 32 variables
  78. myStackStart: .byte 64 ;currently at $1E0.Meets return stack.
  79.  
  80. .CSEG
  81. .ORG 0x800 ;dictionary starts at 4K (2K words) mark
  82. ;----------------------------------------------------
  83. one_1:
  84. .db 0,0,3, "one" ;code for one
  85. one:
  86. ; rcall stackme
  87. rcall stackme_2
  88. .db 01, 00
  89. ret
  90. ;----------------------------------------------
  91. two_1:
  92. header one_1, 3, "two"
  93. two:
  94. rcall stackme_2
  95. .db 02,00
  96. ret
  97. ;------------------------------------------
  98. dup_1:
  99. header two_1,3,"dup"
  100. dup:
  101. mypop r17
  102. mypop r16
  103. mypush r16
  104. mypush r17
  105. mypush r16
  106. mypush r17
  107.  
  108. ret
  109. ;-------------------------------------------
  110. drop_1:
  111. header dup_1,4,"drop"
  112. drop:
  113. mypop r17
  114. mypop r16 ;TODO what if stack pointer goes thru floor?
  115. ret
  116. ;----------------------------------
  117. swapp_1: ;twp p's becasue assembler recognizes avr opcode swap
  118. header drop_1,5, "swapp"
  119. swapp:
  120. mypop2 r17,r16
  121. mypop2 r19,r18
  122. mypush2 r16,r17
  123. mypush2 r18,r19
  124. ret
  125.  
  126.  
  127. ;-------------------------------------------------
  128. ;shift this later
  129.  
  130. S_1:
  131. ;the EOL token that gets put into end of buf1 to stop parsing
  132. header swapp_1,1,"S"
  133. S: ldi r16,02
  134. mov BOTTOM,r16 ;r14 =2 means a nice stop. EOL without errors
  135. clr STOP
  136. inc STOP ;set time-to-quit flag
  137. ret
  138. ;------------------------------------------
  139.  
  140. fetch_1: ;doesn't like label = @-1
  141. ;classic fetch. (adr -- num). Only in RAM
  142. header S_1,1,"@"
  143. fetch:
  144. pushx ;going to use x to point so better save
  145. mypop xh
  146. mypop xl
  147. ld r16,x+
  148. ld r17,x
  149. mypush r16
  150. mypush r17 ; and put them on my stack
  151. popx ;return with x intact and RAM val on my stack
  152. ret
  153. ;dddddddddddddddddddddddddddddddddddddddddddddddd
  154.  
  155. cfetch_1: ;doesn't like label = c@-1
  156. ;classic fetch. (adr -- num). Only in RAM. Do I want y to advance just one byte on mystack
  157. header fetch_1,2,"c@"
  158. cfetch:
  159. pushx ;going to use x to point so better save
  160. mypop xh
  161. mypop xl
  162. ld r16,x+
  163. mypush r16
  164. popx ;return with x intact and RAM val on my stack
  165. ret
  166. ;dddddddddddddddddddddddddddddddddddddddddddddddd
  167.  
  168. store_1: ;classic != "store"(adr num --) . Num is now at cell adr.
  169. header cfetch_1,1,"!"
  170. store:
  171. mypop2 r17,r16 ;there goes the num
  172. pushx
  173. mypop2 xh,xl ;there goes the address
  174. st x+,r16
  175. st x,r17 ;num goes to cell with location=adr
  176. popx
  177. ret
  178. ;ddddddddddddddddddddddddddddddddddddddddddddddddddd
  179.  
  180. cstore_1: ;classic c!= "store"(adr 8-bitnum --) . 8 bit Num is now at cell adr.
  181. header store_1,2,"c!"
  182. cstore:
  183. mypop r16 ;there goes the num. Just 8 bits at this stage.
  184. pushx
  185. mypop2 xh,xl ;there goes the address
  186. st x+,r16
  187. ; st x,r17 ;num goes to cell with location=adr
  188. popx
  189. ret
  190. ;------------------------------------
  191.  
  192. star_1: ;classic 16*16 mulitply (n n -- n*n)
  193. header cstore_1,1,"*"
  194. star:
  195. mypop2 r17,r16
  196. mypop2 r19,r18 ;now have both numbers in r16..r19
  197. rcall mpy16s ; multiply them. Result in r18..r21. Overflow in r20,21
  198. mypush2 r18,r19
  199. ret
  200. ;-----------------------------------------
  201.  
  202. slashMod_1: ;classic /MOD (n m -- n/m rem)
  203. header star_1,4,"/mod"
  204. slashMod:
  205. push r13
  206. push r14 ;this is STOP but is used by div16s, so better save it
  207. mypop2 r19,r18 ; that's m
  208. mypop2 r17,r16 ;that's n
  209. rcall div16s ;the the 16 by 16 bit divsion
  210. mypush2 r16,r17 ;answer ie n/m
  211. mypush2 r14,r15 ;remainder
  212. pop r14
  213. pop r13
  214. ret
  215. ;dddddddddddddddddddddddddddddddddddddddddddd
  216.  
  217. plus_1: ;classic + ( n n -- n+n)
  218. header slashMod_1,1,"+"
  219. plus:
  220. mypop2 r17,r16
  221. mypop2 r19,r18
  222. clc
  223. add r16,r18
  224. adc r17,r19
  225. mypush2 r16,r17
  226. ret
  227. ;--
  228.  
  229. minus_1: ;classic - ( n m -- n-m)
  230. header plus_1,1,"-"
  231. minus:
  232. mypop2 r19,r18
  233. mypop2 r17,r16
  234. clc
  235. sub r16,r18
  236. sbc r17,r19
  237. mypush2 r16,r17
  238. ret
  239. ;dddddddddddddddddddddddddddddddddddddddddd
  240.  
  241. pstore_1: ;expects eg. 0003 PORTB P! etc, "output 3 via PORTB"
  242. header minus_1,2, "p!"
  243. pstore:
  244. mypopb ;get rid of PORTB number, not used for tiny85, just one port
  245. mypopa ; this is used. it's eg the 003 = R16 above
  246. out PORTB,r16
  247. ret
  248. ;ddddddddddddddddddddddddd
  249.  
  250. portblabel_1:
  251. header pstore_1,5,"PORTB" ; note caps just a filler that point 0b in stack for dropping
  252. portblabel:
  253. ; Extend later on to include perhaps other ports
  254. ; one:
  255. ; rcall stackme
  256.  
  257. rcall stackme_2
  258. .db $0b, 00
  259. ret
  260. ;---------------------
  261.  
  262. datadirstore_1: ;set ddrb. invioked like this 000f PORTB dd! to make pb0..pb3 all outputs
  263. header portblabel_1, 3, "dd!"
  264. datadirstore:
  265. mypopb ; there goes useless 0b = PORTB
  266. mypopa ; 000f now in r17:16
  267. out DDRB,r16
  268. ret
  269. ;dddddddddddddddddddddddddddddddddddd
  270. ;sbilabel_1 ;set bit in PORTB. Just a kludge at this stage
  271. ;header datadirstore_1,3,"sbi" TODO sort out sbi and delay later. Now get on with compiler.
  272. ;first need store system vars in the eeprom. Arbitrarily 0010 is HERE and 0012 (in eeprom) is LATEST
  273. ;----------------------------------------
  274.  
  275. percentcstore_1: ;(n16 adr16 --) %c! stores stack val LSbyte to eeprom adr
  276. ; eg 10 00 1234 stores 34 to 0010 <--eeprom adr
  277. header datadirstore_1,3,"%c!"
  278. percentcstore:
  279. mypopb ;adr in r18,19
  280. mypopa ;data. Lower byte into r16
  281.  
  282. rcall eewritebyte ;burn it into eeprom
  283. ret
  284. ;----------------------------------
  285.  
  286. percentstore_1: ; (n16 adr16 --) b16 stored at eeprom adr adr16 and adr16+1
  287. header percentcstore_1,2, "%!"
  288. percentstore:
  289. mypopb ;adr in b=r18,19
  290. mypopa ;n16 into r16,17 as data
  291.  
  292. rcall eewritebyte ;burn low data byte
  293. clc
  294. inc r18
  295. brne outpcs
  296. inc r17 ;sets up adr+1 for next byte
  297. outpcs:
  298. mov r16,r17 ;r16 now conatins hi byte
  299. rcall eewritebyte
  300. ret
  301. ;-------------------------------
  302.  
  303. percentcfetch_1: ;(eepromadr16--char). Fetch eeprom byte at adr on stack
  304. header percentstore_1,3,"%c@"
  305. percentcfetch:
  306. mypopb ;adr now in r18,19
  307. rcall eereadbyte
  308. mypush r16 ; there's the char going on stack. Should be n16? Not n8?
  309. ret
  310. ;-------------------
  311.  
  312. percentfetch_1: ;(adr16--n16) get 16bits at adr and adr+1
  313. header percentcfetch_1,2,"%@"
  314. percentfetch:
  315. rcall percentcfetch ;low byte now on stack
  316. inc r18
  317. brcc downpf
  318. inc r19
  319. downpf:
  320. rcall eereadbyte ;there's the high byte hitting the mystack
  321. mypush r16
  322. ret
  323. ;-------------------------------
  324. gethere_1: ; leaves current value of eHERE on stack
  325. header percentfetch_1,7,"gethere"
  326. gethere:
  327. rcall stackme_2
  328. .dw eHere
  329. rcall percentfetch
  330. ret
  331. ;--------------------
  332.  
  333. getlatest_1: ;leaves current value of latest on stack
  334. header gethere_1,9, "getlatest"
  335. getlatest:
  336. rcall stackme_2
  337. .dw eLATEST ;the address of the latest link lives in eeprom at address 0012
  338. rcall percentfetch ;get the val out of eeprom
  339. ret
  340. ;------------------
  341. LATEST:
  342. colon_1: ;classic ":"compiling new word marker
  343. header getlatest_1,1,":"
  344. rcall coloncode
  345. ret
  346. ;----------------------------------------
  347. HERE:
  348. .db $12,$34, 6, "mxword"
  349.  
  350.  
  351.  
  352.  
  353.  
  354.  
  355.  
  356.  
  357.  
  358.  
  359.  
  360.  
  361.  
  362.  
  363. ;-------------------------------------------------
  364. stackme_2: ;stacks on my stack next 16bit num. Address of 16bit number is on SP-stack
  365. ; Used like this stackme_2 0034. Puts 0034 on myStack and increments past number on return stack.
  366. pop r17
  367. pop r16 ; they now contain eg 0x0804 which contain the 16bit num
  368. movw zl,r16 ;z now points to cell that cobtains the number
  369. clc
  370. rol zl
  371. rol zh ;double word address for z. lpm coming up
  372.  
  373.  
  374.  
  375. lpm r16,z+
  376. lpm r17,z+ ;now have 16bit number in r16,17
  377.  
  378. st y+,r16
  379. st y+, r17 ;mystack now contains the number
  380.  
  381. clc
  382. ror zh
  383. ror zl ;halve the z pointer to step past the number to return at the right place
  384.  
  385. push zl
  386. push zh
  387.  
  388. ret
  389.  
  390.  
  391.  
  392. ;====================================================================================================
  393.  
  394. .ORG 0
  395. rjmp start
  396. ;typein: .db "11bb 0014 %! getlatest",$0d, "0013 %@",0x0d
  397.  
  398. typein: .db "one : myword two " ,$0d
  399. ;"11bb 0014 %! ", $0d ;%! getlatest",$0d, "0013 %@",0x0d
  400. ;" one 0010 00ab %c! 0012 cdef %! 0013 %c@ 0013 %@ 0987 drop ", 0x0d
  401.  
  402. ;stackme dropx onex stackme swap drop",0x0d
  403. start:
  404. ldi r16, low(RAMEND)
  405. out SPL, r16
  406.  
  407.  
  408. ldi r16,high(RAMEND)
  409. out SPH, r16
  410.  
  411. ldi YL,low(myStackStart)
  412. ldi YH,high(myStackStart)
  413. rcall burneepromvars
  414.  
  415.  
  416. ;rjmp test_interpretLine
  417. ;rjmp test_cfetch
  418. ;rjmp test_store
  419. ;rjmp test_cstore
  420. ;rjmp test_mpy16s
  421. ;rjmp test_mpy16s0
  422. ;rjmp test_star
  423. ;rjmp test_div16s
  424. ;rjmp test_slashMod
  425. ;rjmp test_Hex4ToBin2
  426. rjmp test_interpretLine
  427. ;rjmp setupforflashin
  428. ;rcall coloncode
  429. ;zzz
  430.  
  431. stopper: rjmp stopper
  432. ; rjmp start
  433.  
  434. getline0: ;force a line into buf1 via flash string. Simulates GETLINE
  435. ldi zl, low(typein<<1)
  436. ldi zh, high(typein<<1)
  437. ldi xl, low(buf1)
  438. ldi xh, high(buf1)
  439. type0:
  440. lpm r16,Z+
  441. st x+,r16
  442. cpi r16,0x0d ;have we got to the end of the line?
  443. brne type0
  444. ret
  445. ;--------------------------------------------
  446. ;WORD gets x to point to start of word (copy in w=r24,25) with the length in len = r20
  447. ;assume word points to somewhere in buf1. Should advance thru spaces=0x20 to first real char
  448. word: ;maybe give it a header later
  449. ld r16,x+ ;get char
  450. ld SECONDLETTER, x ;for debugging
  451.  
  452. cpi r16,0x20 ;is it a space?
  453. breq word ;if so get next char
  454. ;if here we're point to word start. so save this adr in w
  455. mov r24,xl
  456. mov r25,xh ;wordstart now saved in w
  457.  
  458.  
  459. clr r20 ;length initially 0
  460. nextchar:
  461. inc r20 ;r20 = word length
  462. ld r16,x+ ;get next char
  463. cpi r16,0x20
  464. brne nextchar
  465. dec r24 ;adjust start of word
  466. ;if here we've found a word.Starting at w length in r20.x points to space just past word
  467. ret
  468. ;----------------------------------------
  469.  
  470. compare: ;given a word in buf1 and a word in the dic are they the same? The word in the dic is pointed to by Z.
  471. ; and the word in buf1 is pointed to by w=r24,25. len = r20. Z on entry points to the link. Needs +2 to
  472. lpm r23,z+
  473. lpm r22,z+ ;store next link in v=r22,23. z now points to len byte
  474.  
  475. startc:
  476. ;TODO save copy of flash word in r21 and also do masking of immediates
  477. push r20 ;save length
  478. lpm r16,Z+ ;length of dictionary word, first entry now in r16
  479. mov r21,r16 ;copy length-in-flash to r21. May have immediate bit (bit 7)
  480. andi r16,$0f ;mask off top nibble before comparing
  481. cp r16,r20 ;same lengths?
  482. brne outcom ;not = so bail out
  483. ;if here the words are the same length, what about the rest of the chars.First get x to point to word.
  484. mov xl,r24
  485. mov xh,r25 ;x now point to start of buf1 word
  486. upcom:
  487. lpm r16,z+
  488. ld r17,x+ ;get one corresponding char from each word
  489. cp r16,r17 ;same word?
  490. brne outcom ;bail out if chars are different
  491. dec r20 ;count chars
  492. brne upcom ;still matching and not finished so keep going
  493. ;if here r20 is 0 so match must have been perfect so FOUND = 1
  494. clr FOUND
  495. inc FOUND
  496. outcom:
  497. pop r20 ;get old lngth of buf1 word back
  498. ret
  499. ;-------------------------------------------
  500. jmpNextWord: ;go to next word in the dictionary. Assume v=r22,23 contains next link word(not byte)
  501. ; and w = r24,25 contains RAM word start with len in r20
  502. ;exit with z pointing to next word ready for next COMPARE.
  503. clc
  504. rol r22
  505. rol r23 ;above 3 instructions change word address into byte address by doubling
  506. movw r30,r22 ;z now points to next word
  507. ret
  508. ;-----------------------------------------
  509.  
  510. doLatest: ;set up so first jump in dictionary is to top=LATEST and other flags set up.
  511. ldi vl, low(LATEST)
  512. ldi vh, high(LATEST)
  513. clr FOUND
  514. clr BOTTOM ;not yet found the match, not yet at the bottom. Either will stop search.
  515. clr STOP ;keep parsing words til this goes to a 1
  516. ret
  517. ;---------------------------------------------
  518. interpretLine: ;given line of words in buf one, search for words one by one. Don't do code
  519. ; or compile at this stage, just find and report that and go into next one.
  520. rcall getline0 ;change later to real getline via terminal
  521. rcall pasteEOL
  522. ldi xl, low(buf1)
  523. ldi xh,high(buf1) ;last 3 statemnts are done onece. Now the main loop.
  524. clr FOUNDCOUNTER ;counts finds in line parsing.
  525.  
  526. nextWord:
  527. tst STOP
  528. brne stopLine
  529. rcall word
  530. rcall findWord ;not done yet
  531. rcall dealWithWord ;go and run code STATE=0, or compile (STATE =1).{ c0de, comp1le}
  532. rjmp nextWord
  533. stopLine:
  534. ret
  535. ;-----------------------------------------------------------------
  536. findWord:
  537. rcall doLatest
  538. upjmpf:
  539. rcall jmpNextWord
  540. rcall compare
  541. tst FOUND
  542. brne stopsearchf ;if last compare got a match (FOUND=1) then stop searching
  543. tst vl
  544. brne upjmpf ;if v=0000 then we've hit the bottom of the dictionary
  545. tst vh
  546. brne upjmpf ;not found and not at bottom so keep going
  547. ;if here FOUND =0, ie no match yet and we've hit the bottom of the dictionary
  548. clr BOTTOM
  549. inc BOTTOM ;exit with FOUND=0 and BOTTOM =1
  550. stopsearchf: nop
  551. ret
  552. ;----------------------------
  553. test_interpretLine:
  554. rcall interpretLine
  555. til: rjmp til ;** with r24 pointing to 'S' and FOUND = r15 =1
  556. ;------------------------------
  557. dealWithWord: ;come here when it's time to compile or run code
  558. ;Good debugging spot. Enter here with Z pointing to CFA of word found. Y points to myStack. X points to just
  559. ; past the word we are seeking (w-s). r10 is 2nd letter of w-s. w = start adr of w-s. v is a link
  560. ; to the next word in dic. Either just below the found word or 0000 if we get to the bottome with no match
  561. ;
  562. nop
  563. tst FOUND
  564. breq notfound
  565. inc FOUNDCOUNTER
  566.  
  567. ;want to hop over filler bytes,0's added to keep codes on even byte boundaries
  568. ; so if r30 is odd at this stage inc it. odd is lsbit = 1.
  569. sbrs r30,0 ;skip next instruction if final bit lsb = 1
  570. rjmp downdw
  571. ;if here lsb = 1 so we're on a padding byte and have to add 1 to get to a 2 byte boundary
  572. inc r30
  573. brcc downdw
  574. inc r31 ;add one to z before converting to bytes
  575.  
  576. downdw: tst STATE
  577. breq executeme
  578. rcall compilecode
  579. executeme:
  580. clc
  581. ror zh
  582. ror zl ;put z back into word values
  583.  
  584.  
  585. rcall executeCode
  586.  
  587.  
  588.  
  589. .MESSAGE "Word found"
  590. rjmp outdww
  591. notfound:
  592. nop
  593. ; .MESSAGE "Word not found"
  594. ; clr STOP
  595. ; inc STOP ;stop parsing line
  596. rcall numberh ; word not in dict so must be a number? Form = HHHH
  597. ;now have to add 3 to x so it points past this word ready not next one
  598. clc
  599. inc r26
  600. inc r26
  601. inc r26
  602. brcc outdww
  603. inc r27 ;but only if overflow
  604. nop
  605. outdww:
  606. ret ;with STOP =1 in not a number
  607. ;------------------------------------------------------------------------
  608. pasteEOL: ;when a line of text is TYPEd into buf1 it should end with CR=$0d. This gets replaced with ]}, a
  609. ; special end of line word. When the word is invoked it casues a QUIT back to the waiting for input stage.
  610. ; Start at buf1 start and inspect each char for a $0D. When found replace with a "$20 S $20 "
  611. ldi xl, low(buf1)
  612. ldi xh, high(buf1) ;pnt to start of buffer
  613. clr r17
  614. nxtChar:
  615. inc r17 ;r17 is counter. Bail out when r17 > BUF1LENGTH
  616. cpi r17, BUF1LENGTH -3
  617. breq outProb
  618. ld r16, x+
  619. cpi r16, $0d
  620. brne nxtChar
  621. ;if here we've found a $0d in buf1 before the end, so replace with an EOL token. x points to just after it.
  622. ldi r16,$20
  623. st -x, r16 ;back up. Then go forward.
  624. ; ldi r16, ']'
  625. st x+, r16
  626. ldi r16,'S'
  627. st x+, r16
  628. ; ldi r16, '}'
  629. ; st x+, r16
  630. ldi r16, $20
  631. st x, r16
  632. rjmp outpel
  633.  
  634.  
  635. outProb:
  636. nop
  637. .MESSAGE "Couldn't find $0d"
  638. outpel:
  639. ret
  640.  
  641. ;-------------------------------------
  642. executeCode: ;with Z pointing to cfa. Not sure whether to jmp or call
  643.  
  644. ijmp
  645. ret
  646. ;---------------------------------------
  647. test_fetch: ;do run thru of @
  648. rcall getline0 ;change later to real getline via terminal
  649. rcall pasteEOL
  650. ldi xl, low(buf1)
  651. ldi xh,high(buf1) ;last 3 statemnts are done onece. Now the main loop.
  652.  
  653. ldi r16,$62
  654. mypush r16
  655. ldi r16,$0
  656. mypush r16 ;should now have adr $0062 on mystack
  657. rcall fetch
  658. tf1:
  659. rjmp tf1
  660. ;---------------------------------
  661. test_cfetch: ;do run thru of @
  662. rcall getline0 ;change later to real getline via terminal
  663. rcall pasteEOL
  664. ldi xl, low(buf1)
  665. ldi xh,high(buf1) ;last 3 statemnts are done onece. Now the main loop.
  666.  
  667. ldi r16,$62
  668. mypush r16
  669. ldi r16,$0
  670. mypush r16 ;should now have adr $62 on mystack
  671. rcall cfetch
  672. tcf1:
  673. rjmp tcf1
  674. ;----------------------------
  675. test_store:
  676. rcall getline0 ;change later to real getline via terminal
  677. rcall pasteEOL
  678. ldi xl, low(buf1)
  679. ldi xh,high(buf1) ;last 3 statemnts are done onece. Now the main loop.
  680. ldi r16,$62
  681. ldi r17,$0
  682. mypush2 r16,r17 ;should now have adr $62 on mystack
  683. ldi r16, $AB
  684. ldi r17, $CD
  685. mypush2 r16,r17 ;now have $ABCD on mystack
  686. rcall store
  687. ts1:
  688. rjmp ts1
  689. ;------------------------
  690. test_cstore:
  691. rcall getline0 ;change later to real getline via terminal
  692. rcall pasteEOL
  693. ldi xl, low(buf1)
  694. ldi xh,high(buf1) ;last 3 statemnts are done onece. Now the main loop.
  695. ldi r16,$62
  696. ldi r17,$0
  697. mypush2 r16,r17 ;should now have adr $62 on mystack
  698. ldi r16, $AB
  699. ; ldi r17, $CD
  700. mypush r16 ;now have $ABCD on mystack
  701. rcall cstore
  702.  
  703. ts11:
  704. rjmp ts11
  705. ;Now put arith routines here. Are from AVR200. Just using 16*16 for * but get 32bit result.
  706.  
  707.  
  708. ;***************************************************************************
  709. ;*
  710. ;* "mpy16s" - 16x16 Bit Signed Multiplication
  711. ;*
  712. ;* This subroutine multiplies signed the two 16-bit register variables
  713. ;* mp16sH:mp16sL and mc16sH:mc16sL.
  714. ;* The result is placed in m16s3:m16s2:m16s1:m16s0.
  715. ;* The routine is an implementation of Booth's algorithm. If all 32 bits
  716. ;* in the result are needed, avoid calling the routine with
  717. ;* -32768 ($8000) as multiplicand
  718. ;*
  719. ;* Number of words :16 + return
  720. ;* Number of cycles :210/226 (Min/Max) + return
  721. ;* Low registers used :None
  722. ;* High registers used :7 (mp16sL,mp16sH,mc16sL/m16s0,mc16sH/m16s1,
  723. ;* m16s2,m16s3,mcnt16s)
  724. ;*
  725. ;***************************************************************************
  726.  
  727. ;***** Subroutine Register Variables
  728.  
  729. .def mc16sL =r16 ;multiplicand low byte
  730. .def mc16sH =r17 ;multiplicand high byte
  731. .def mp16sL =r18 ;multiplier low byte
  732. .def mp16sH =r19 ;multiplier high byte
  733. .def m16s0 =r18 ;result byte 0 (LSB)
  734. .def m16s1 =r19 ;result byte 1
  735. .def m16s2 =r20 ;result byte 2
  736. .def m16s3 =r21 ;result byte 3 (MSB)
  737. .def mcnt16s =r22 ;loop counter
  738.  
  739. ;***** Code
  740. mpy16s: clr m16s3 ;clear result byte 3
  741. sub m16s2,m16s2 ;clear result byte 2 and carry
  742. ldi mcnt16s,16 ;init loop counter
  743. m16s_1: brcc m16s_2 ;if carry (previous bit) set
  744. add m16s2,mc16sL ; add multiplicand Low to result byte 2
  745. adc m16s3,mc16sH ; add multiplicand High to result byte 3
  746. m16s_2: sbrc mp16sL,0 ;if current bit set
  747. sub m16s2,mc16sL ; sub multiplicand Low from result byte 2
  748. sbrc mp16sL,0 ;if current bit set
  749. sbc m16s3,mc16sH ; sub multiplicand High from result byte 3
  750. asr m16s3 ;shift right result and multiplier
  751. ror m16s2
  752. ror m16s1
  753. ror m16s0
  754. dec mcnt16s ;decrement counter
  755. brne m16s_1 ;if not done, loop more
  756. ret
  757. ;----------------------------------------------------------
  758. ;***** Multiply Two Signed 16-Bit Numbers (-12345*(-4321))
  759. test_mpy16s:
  760. ldi mc16sL,low(-12345)
  761. ldi mc16sH,high(-12345)
  762. ldi mp16sL,low(-4321)
  763. ldi mp16sH,high(-4321)
  764. rcall mpy16s ;result: m16s3:m16s2:m16s1:m16s0
  765. ;=$032df219 (53,342,745)
  766. tmpy: rjmp tmpy
  767.  
  768. test_mpy16s0:
  769. ldi mc16sL,low(123)
  770. ldi mc16sH,high(123)
  771. ldi mp16sL,low(147)
  772. ldi mp16sH,high(147)
  773. rcall mpy16s ;result: m16s3:m16s2:m16s1:m16s0
  774. tmpy0: rjmp tmpy0
  775. ;-----------------------
  776. test_star:
  777. ldi r16,-$7b
  778. mypush r16
  779. ldi r16,$00
  780. mypush r16 ;that's decimal 123 on stack
  781. ldi r16,$93
  782. mypush r16
  783. ldi r16,$00
  784. mypush r16 ; and thats dec'147
  785. rcall star
  786. tsr: rjmp tsr
  787.  
  788. ;--------------------------
  789. ;***************************************************************************
  790. ;*
  791. ;* "div16s" - 16/16 Bit Signed Division
  792. ;*
  793. ;* This subroutine divides signed the two 16 bit numbers
  794. ;* "dd16sH:dd16sL" (dividend) and "dv16sH:dv16sL" (divisor).
  795. ;* The result is placed in "dres16sH:dres16sL" and the remainder in
  796. ;* "drem16sH:drem16sL".
  797. ;*
  798. ;* Number of words :39
  799. ;* Number of cycles :247/263 (Min/Max)
  800. ;* Low registers used :3 (d16s,drem16sL,drem16sH)
  801. ;* High registers used :7 (dres16sL/dd16sL,dres16sH/dd16sH,dv16sL,dv16sH,
  802. ;* dcnt16sH)
  803. ;*
  804. ;***************************************************************************
  805.  
  806. ;***** Subroutine Register Variables
  807.  
  808. .def d16s =r13 ;sign register
  809. .def drem16sL=r14 ;remainder low byte
  810. .def drem16sH=r15 ;remainder high byte
  811. .def dres16sL=r16 ;result low byte
  812. .def dres16sH=r17 ;result high byte
  813. .def dd16sL =r16 ;dividend low byte
  814. .def dd16sH =r17 ;dividend high byte
  815. .def dv16sL =r18 ;divisor low byte
  816. .def dv16sH =r19 ;divisor high byte
  817. .def dcnt16s =r20 ;loop counter
  818.  
  819. ;***** Code
  820.  
  821. div16s: ;push r13 ;PB !!
  822. ;push r14 ;PB !!
  823. mov d16s,dd16sH ;move dividend High to sign register
  824. eor d16s,dv16sH ;xor divisor High with sign register
  825. sbrs dd16sH,7 ;if MSB in dividend set
  826. rjmp d16s_1
  827. com dd16sH ; change sign of dividend
  828. com dd16sL
  829. subi dd16sL,low(-1)
  830. sbci dd16sL,high(-1)
  831. d16s_1: sbrs dv16sH,7 ;if MSB in divisor set
  832. rjmp d16s_2
  833. com dv16sH ; change sign of divisor
  834. com dv16sL
  835. subi dv16sL,low(-1)
  836. sbci dv16sL,high(-1)
  837. d16s_2: clr drem16sL ;clear remainder Low byte
  838. sub drem16sH,drem16sH;clear remainder High byte and carry
  839. ldi dcnt16s,17 ;init loop counter
  840.  
  841. d16s_3: rol dd16sL ;shift left dividend
  842. rol dd16sH
  843. dec dcnt16s ;decrement counter
  844. brne d16s_5 ;if done
  845. sbrs d16s,7 ; if MSB in sign register set
  846. rjmp d16s_4
  847. com dres16sH ; change sign of result
  848. com dres16sL
  849. subi dres16sL,low(-1)
  850. sbci dres16sH,high(-1)
  851. d16s_4: ;pop r14 ;PB!!
  852. ;pop r13 ;PB!!
  853. ret ; return
  854. d16s_5: rol drem16sL ;shift dividend into remainder
  855. rol drem16sH
  856. sub drem16sL,dv16sL ;remainder = remainder - divisor
  857. sbc drem16sH,dv16sH ;
  858. brcc d16s_6 ;if result negative
  859. add drem16sL,dv16sL ; restore remainder
  860. adc drem16sH,dv16sH
  861. clc ; clear carry to be shifted into result
  862. rjmp d16s_3 ;else
  863. d16s_6: sec ; set carry to be shifted into result
  864. rjmp d16s_3
  865.  
  866. ;-----------------------------------------------
  867.  
  868. test_div16s:
  869. ;***** Divide Two Signed 16-Bit Numbers (-22,222/10)
  870. ldi dd16sL,low(-22222)
  871. ldi dd16sH,high(-22222)
  872. ldi dv16sL,low(10)
  873. ldi dv16sH,high(10)
  874. rcall div16s ;result: $f752 (-2222)
  875. ;remainder: $0002 (2)
  876.  
  877. forever:rjmp forever
  878. ;----------------------------------
  879. test_slashMod:
  880. ldi r16,$12
  881. mypush r16
  882. ldi r16,$34
  883. mypush r16
  884. ldi r16,$56 ;NB this is $3412 not $1234
  885. mypush r16
  886. ldi r16,$00
  887. mypush r16
  888. rcall slashMod ;$3412 / $56 = $9b rem 0 works
  889. tslm: rjmp tslm
  890.  
  891. ;---------------------------------------
  892. ;From http://www.avr-asm-tutorial.net/avr_en/calc/CONVERT.html#hex2bin
  893. ; Hex4ToBin2
  894. ; converts a 4-digit-hex-ascii to a 16-bit-binary
  895. ; In: Z points to first digit of a Hex-ASCII-coded number
  896. ; Out: T-flag has general result:
  897. ; T=0: rBin1H:L has the 16-bit-binary result, Z points
  898. ; to the first digit of the Hex-ASCII number
  899. ; T=1: illegal character encountered, Z points to the
  900. ; first non-hex-ASCII character
  901. ; Used registers: rBin1H:L (result), R0 (restored after
  902. ; use), rmp
  903. ; Called subroutines: Hex2ToBin1, Hex1ToBin1
  904.  
  905. .def rBin1H =r17
  906. .def rBin1L = r16
  907. .def rmp = r18
  908. ;
  909. Hex4ToBin2:
  910. clt ; Clear error flag
  911. rcall Hex2ToBin1 ; convert two digits hex to Byte
  912. brts Hex4ToBin2a ; Error, go back
  913. mov rBin1H,rmp ; Byte to result MSB
  914. rcall Hex2ToBin1 ; next two chars
  915. brts Hex4ToBin2a ; Error, go back
  916. mov rBin1L,rmp ; Byte to result LSB
  917. sbiw ZL,4 ; result ok, go back to start
  918. Hex4ToBin2a:
  919. ret
  920. ;
  921. ; Hex2ToBin1 converts 2-digit-hex-ASCII to 8-bit-binary
  922. ; Called By: Hex4ToBin2
  923. ;
  924. Hex2ToBin1:
  925. push R0 ; Save register
  926. rcall Hex1ToBin1 ; Read next char
  927. brts Hex2ToBin1a ; Error
  928. swap rmp; To upper nibble
  929. mov R0,rmp ; interim storage
  930. rcall Hex1ToBin1 ; Read another char
  931. brts Hex2ToBin1a ; Error
  932. or rmp,R0 ; pack the two nibbles together
  933. Hex2ToBin1a:
  934. pop R0 ; Restore R0
  935. ret ; and return
  936. ;
  937. ; Hex1ToBin1 reads one char and converts to binary
  938. ;
  939. Hex1ToBin1:
  940. ld rmp,z+ ; read the char
  941. subi rmp,'0' ; ASCII to binary
  942. brcs Hex1ToBin1b ; Error in char
  943. cpi rmp,10 ; A..F
  944. brcs Hex1ToBin1c ; not A..F
  945. cpi rmp,$30 ; small letters?
  946. brcs Hex1ToBin1a ; No
  947. subi rmp,$20 ; small to capital letters
  948. Hex1ToBin1a:
  949. subi rmp,7 ; A..F
  950. cpi rmp,10 ; A..F?
  951. brcs Hex1ToBin1b ; Error, is smaller than A
  952. cpi rmp,16 ; bigger than F?
  953. brcs Hex1ToBin1c ; No, digit ok
  954. Hex1ToBin1b: ; Error
  955. sbiw ZL,1 ; one back
  956. set ; Set flag
  957. Hex1ToBin1c:
  958. ret ; Return
  959. ;--------------------------------------
  960. test_Hex4ToBin2:
  961. pushz
  962. ldi zl,$60
  963. clr zh ;z now points to start of buf1
  964. ldi r16,'0'
  965. st z+,r16
  966. ldi r16,'f'
  967. st z+,r16
  968. ldi r16,'2'
  969. st z+,r16
  970. ldi r16,'3'
  971. st z+,r16
  972. ldi zl,$60
  973. clr zh ;z now points back to start of buf1
  974. rcall Hex4ToBin2
  975. popz
  976. th4: rjmp th4
  977. ;-------------------------------------
  978. numberh: ;word not in dictionary. Try to convert it to hex.
  979. pushz ;algorithm uses z, pity
  980. movw zl,r24 ;r4,25 = w holds start of current word
  981. ;z now points eg to '12ab'start. If t=0 then it coverts to real hex
  982. rcall hex4ToBin2 ;try to convert
  983. ;above call needs 4 hex digits to emerge with t=0 and binary in r16,17
  984. ;want this. If t=0 stack r16,17 and carry on interpreting, else emerge with
  985. ; t=1 and zpointing to first problem char
  986. brtc gotHex
  987. ; if here there's a problem that z is pointing to. Bail out of interpret line
  988. clr STOP
  989. inc STOP
  990. rjmp outnh
  991.  
  992. gotHex: ;sucess.Real hex in r16,17
  993. mypush2 r16,r17 ; so push num onto mystack
  994. outnh:
  995. popz ; but will it be pointing to "right"place in buf1? Yes now OK
  996.  
  997. ret
  998. ; numberh not working fully, ie doesn't point to right place after action.
  999. ; also no action if not a number? DONE better save this first.
  1000. ;---------------------------------
  1001. ;eeroutines
  1002. eewritebyte: ;write what's in r16 to eeprom adr in r18,19
  1003. sbic EECR,EEPE
  1004. rjmp eewritebyte ;keep looping til ready to write
  1005. ;if here the previous write is all done and we can write the next byte to eeprom
  1006. out EEARH,r19
  1007. out EEARL,r18 ;adr done
  1008. out EEDR,r16 ;byte in right place now
  1009. sbi EECR,EEMPE
  1010. sbi EECR,EEPE ;last 2 instruc write eprom. Takes 3.4 ms
  1011. ret
  1012. ;test with %!
  1013. ;---------------------------------
  1014. eereadbyte: ; read eeprom byte at adr in r18,19 into r16
  1015. ; Wait for completion of previous write
  1016. sbic EECR,EEPE
  1017. rjmp eereadbyte
  1018. ; Set up address (r18:r17) in address register
  1019. out EEARH, r19
  1020. out EEARL, r18
  1021. ; Start eeprom read by writing EERE
  1022. sbi EECR,EERE
  1023. ; Read data from data register
  1024. in r16,EEDR
  1025. ret
  1026. ;------------------------------
  1027. setupforflashin: ;using here etc get appropriate page, offset,myhere values.
  1028. ldi r16,low(HERE)
  1029. ldi r17,high(HERE) ;get here, but from eeprom better?
  1030. mypush2 r16,r17
  1031. rcall stackme_2
  1032. .dw 0002
  1033. rcall star ;now have current HERE in bytes in flash. But what is myhere?
  1034. rcall stackme_2
  1035. .db $0040 ;64 bytes per page
  1036. rcall slashMod
  1037. ;offset on top pagenum under. eg pg 0047, offset 0012
  1038. mypop2 r9,r8 ;store offset (in bytes)
  1039. rcall stackme_2
  1040. .db $0040
  1041. rcall star ;pgnum*64 = byte adr of start of flash page
  1042. mypop2 r7,r6
  1043. mypush2 r8,r9 ;push back offset
  1044. rcall stackme_2
  1045. .dw buf2
  1046. nop
  1047. ;at this stage we have offset in r8,r9 (0012). Also byte adr of flash page
  1048. ; start in r6,r7.(11c0) Stk is (offset buf2Start --) (0012 00E0 --). Need to
  1049. ; add these two together to get myhere, the pointer to RAM here position.
  1050. rcall plus ;add offset to buf2 start to get myhere (00f2)
  1051. ; put my here in r4,r5 for time being.
  1052. mypop2 r5,r4 ;contains eg 00f2 <--myhere
  1053. pushz ;going to use z so save it
  1054. movw zl,r6 ;r6,7 have byte adr of flsh pg strt
  1055. pushx ;save x
  1056. ldi xl,low(buf2)
  1057. ldi xh,high(buf2) ;point x to start of buf2
  1058. ldi r18,128 ;r18=ctr. Two flash pages = 128 bytes
  1059. upflash:
  1060. lpm r16,z+ ;get byte from flash page
  1061. st x+, r16 ; and put into buf2
  1062. dec r18
  1063. brne upflash
  1064. ;done. Now have two flash pages in ram in buf2. Myhere points to where next
  1065. ; entry will go. Where's page num?
  1066. popx
  1067. popz ;as if nothing happened
  1068.  
  1069.  
  1070. ret
  1071.  
  1072.  
  1073.  
  1074. ;outsufi: rjmp outsufi
  1075. ;-----------------------------------
  1076. burneepromvars: ;send latest versions of eHERE and eLATEST to eeprom
  1077. ldi r16,low(HERE)
  1078. ldi r17,high(HERE)
  1079. mypush2 r16,r17
  1080. ;up top we have .equ eHERE = $0010
  1081. ldi r16,low(eHERE)
  1082. ldi r17,high(eHERE)
  1083. mypush2 r16,r17
  1084. ;now have n16 eadr on stack ready for e!
  1085. rcall percentstore
  1086.  
  1087. ;send latest versions of eLATEST to eeprom
  1088. ldi r16,low(LATEST)
  1089. ldi r17,high(LATEST)
  1090. mypush2 r16,r17
  1091. ;up top we have .equ eLATEST = $0010
  1092. ldi r16,low(eLATEST)
  1093. ldi r17,high(eLATEST)
  1094. mypush2 r16,r17
  1095. ;now have n16 eadr on stack ready for e!
  1096. rcall percentstore
  1097. ret
  1098. ;-------------------------------------------
  1099. coloncode: ;this is the classic colon defining word.
  1100. rcall setupforflashin ;get all the relevant vars and bring in flash to buf2
  1101. rcall relinkcode ; insert link into first cell
  1102. rcall create ;compile word preceeded by length
  1103. rcall leftbrac ;set state to 1, we're compiling
  1104. ret ;now every word gets compiled until we hit ";"
  1105. ;-------------------------
  1106. relinkcode: ;put LATEST into where myhere is pointing and update ptr = myhere
  1107. ;also create mylatest
  1108. rcall getlatest ;now on stack
  1109. mypopa ;latest in r16,17
  1110. pushz ;better save z
  1111. movw mylatest,myhere ;mylatest <-- myhere
  1112. movw zl,myhere ;z now points to next available spot in buf2
  1113. st z+,r16
  1114. st z+,r17 ;now have new link in start of dic word
  1115. movw myhere,zl ;update myhere to point to length byte. (Not yet there.)
  1116. popz ;restore z
  1117. ret
  1118. ;-------------------------------------------------
  1119. create: ;put word after ":" into dictionary, aftyer link, preceeded by len
  1120. rcall word ;start with x pnting just after ":".End with len in r20, x pointing to
  1121. ; space just after word and start of word in w=r24,25
  1122. pushz ;save z. It's going to be used on ram dictionary
  1123. movw zl,myhere ;z now pnts to next spot in ram dic
  1124. st z+,r20 ; put len byte into ram dic
  1125. mov r18,r20 ;use r18 as ctr, don't wreck r20
  1126. pushx ;save x. It's going to be word ptr in buf1
  1127. movw xl,wl ;x now points to start of word. Going to be sent to buf2
  1128. sendbytes:
  1129. ld r16,x+ ;tx byte from buf1 to
  1130. st z+,r16 ; buf2
  1131. dec r18 ;repeat r20=r18=len times
  1132. brne sendbytes
  1133.  
  1134. sbrs r30,0 ;skip next instruction if final bit lsb = 1
  1135. rjmp downcr
  1136. ;if here lsb = 1 so we're on a padding byte and have to add 1 to get to a 2 byte boundary
  1137. clr r16
  1138. st z+,r16 ;insert padding byte
  1139. ;inc r30
  1140. ;brcc downcr
  1141. ;inc r31 ;add one to z before converting to bytes
  1142.  
  1143. downcr:
  1144. movw myhere,zl ;myhere now points to beyond word in dic
  1145. popx
  1146. popz
  1147. ret ;with word in dic
  1148. ;----------------------------------------------
  1149. leftbrac: ;classic turn on compiling
  1150. clr STATE
  1151. inc STATE ;state =1 ==> now compiling
  1152. ret
  1153. ;------------------------
  1154. compilecode: ;come here with STATE =1 ie compile, not execute. Want to put
  1155. ; eg rcall dup in code in dictionary but not to execute dup. If here
  1156. ; z points to byte address of word
  1157. mypush2 zl,zh
  1158. mypush2 myhere,r5 ;push ptr to RAM dic
  1159. ldi r16,low(buf2)
  1160. ldi r17,high(buf2) ;start of buf that conatins flash pg in RAM
  1161. mypush2 r16,r17
  1162. rcall minus ; myhere - buf2-start = offset in page
  1163. mypush2 SOFPG,r7 ;push start of flash page address
  1164. rcall plus ;SOFPG + offset = adr of next rcall in dic
  1165. ;if here we have two flash addresses on the stack. TOS = here. Next is there.
  1166. ;want to insert code for "rcall there w"hen I'm at here. eg current debugging indicates
  1167. ; here = $11EB and there is $1012 (cfa of "two"). First compute
  1168. ; relative branch "there - here -2". Then fiddle this val into the rcall opcode
  1169. rcall minus ;that;s there - here. Usu negative.
  1170. ;I got fffffffff..ffe27 for above vals. First mask off all those f's
  1171. rcall two ;stack a 2
  1172. rcall minus ;now have there-here -2 = fe24. When there,here in bytes.
  1173. mypopa ;bring fe26 into r16,17
  1174. clc
  1175. ror r17
  1176. ror r16 ;now a:= a/2
  1177. ldi r18,$ff
  1178. ldi r19,$0f ;mask
  1179. and r16,r18
  1180. and r17,r19
  1181. ; mypush2 r16,r17 ;now fe26 --> 0e26
  1182. ;the rcall opcode is Dxxx where xxx is the branch
  1183. ; mypopa ;bring fe26 into r16,17
  1184. ldi r19, $d0 ;mask
  1185. or r17,r19
  1186. mypush2 r16,r17 ;now have $de26 on stack which is (?) rcall two
  1187. ret
  1188. ;---------------------------
  1189. ;call two
  1190. ;nop
Advertisement
Add Comment
Please, Sign In to add comment