prjbrook

forth85_14 start of colon, link, create

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