prjbrook

forth85_10

Jul 17th, 2014
277
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 23.50 KB | None | 0 0
  1. ;this is forth85_10.
  2. ;main task here is to get + and - going.
  3. ;These seem to be working in simulator on avrStudio 4. +, - PORTB, p!
  4. ;Next task; dd! p@
  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.  
  50.  
  51.  
  52. .def FOUND = r15 ;if found=1 we have a match of Ram word on dictionary
  53. .def BOTTOM = r14 ;have hit the bottom of the dict and not found a match
  54. .def STOP = r13 ;stop interpreting line of words
  55. .def STATE = r12
  56. .def FOUNDCOUNTER = r11 ;dealWithWord clicks this if found =1. Counts successful finds in dictionary.
  57. .def SECONDLETTER =r10 ;helpful for debugging
  58. .def vl = r22
  59. .def vh = r23 ; u,v,w,x,y,z are all pointers
  60. .DSEG
  61. .ORG 0x60
  62.  
  63. ;consts: .DB "jksdafhsdf",8, 255, 0b01010101, -128, 0xaa
  64. .equ BUF1LENGTH = 64
  65.  
  66. buf1: .byte BUF1LENGTH
  67. buf2: .byte 64 ;could have third buffer?
  68. varSpace: .byte 64 ;might need more than 32 variables
  69. ;.org 0x1E0
  70. myStackStart: .byte 64
  71.  
  72. .cseg
  73. .ORG 0x800 ;dictionary starts at 4K (2K words) mark
  74. ;----------------------------------------------------
  75. one_1:
  76. .db 0,0,3, "one" ;code for one
  77. one:
  78. ; rcall stackme
  79. rcall stackme_2
  80. .db 01, 00
  81. ret
  82. ;----------------------------------------------
  83. two_1:
  84. header one_1, 3, "two"
  85. two:
  86. rcall stackme_2
  87. .db 02,00
  88. ret
  89. ;------------------------------------------
  90. dup_1:
  91. header two_1,3,"dup"
  92. dup:
  93. mypop r17
  94. mypop r16
  95. mypush r16
  96. mypush r17
  97. mypush r16
  98. mypush r17
  99.  
  100. ret
  101. ;-------------------------------------------
  102. drop_1:
  103. header dup_1,4,"drop"
  104. drop:
  105. mypop r17
  106. mypop r16 ;TODO what if stack pointer goes thru floor?
  107. ret
  108. ;----------------------------------
  109. swapp_1: ;twp p's becasue assembler recognizes avr opcode swap
  110. header drop_1,5, "swapp"
  111. swapp:
  112. mypop2 r17,r16
  113. mypop2 r19,r18
  114. mypush2 r16,r17
  115. mypush2 r18,r19
  116. ret
  117.  
  118.  
  119. ;-------------------------------------------------
  120. ;shift this later
  121.  
  122. S_1:
  123. ;the EOL token that gets put into end of buf1 to stop parsing
  124. header swapp_1,1,"S"
  125. S: ldi r16,02
  126. mov BOTTOM,r16 ;r14 =2 means a nice stop. EOL without errors
  127. clr STOP
  128. inc STOP ;set time-to-quit flag
  129. ret
  130. ;------------------------------------------
  131.  
  132. fetch_1: ;doesn't like label = @-1
  133. ;classic fetch. (adr -- num). Only in RAM
  134. header S_1,1,"@"
  135. fetch:
  136. pushx ;going to use x to point so better save
  137. mypop xh
  138. mypop xl
  139. ld r16,x+
  140. ld r17,x
  141. mypush r16
  142. mypush r17 ; and put them on my stack
  143. popx ;return with x intact and RAM val on my stack
  144. ret
  145. ;dddddddddddddddddddddddddddddddddddddddddddddddd
  146.  
  147. cfetch_1: ;doesn't like label = c@-1
  148. ;classic fetch. (adr -- num). Only in RAM. Do I want y to advance just one byte on mystack
  149. header fetch_1,2,"c@"
  150. cfetch:
  151. pushx ;going to use x to point so better save
  152. mypop xh
  153. mypop xl
  154. ld r16,x+
  155. mypush r16
  156. popx ;return with x intact and RAM val on my stack
  157. ret
  158. ;dddddddddddddddddddddddddddddddddddddddddddddddd
  159.  
  160. store_1: ;classic != "store"(adr num --) . Num is now at cell adr.
  161. header cfetch_1,1,"!"
  162. store:
  163. mypop2 r17,r16 ;there goes the num
  164. pushx
  165. mypop2 xh,xl ;there goes the address
  166. st x+,r16
  167. st x,r17 ;num goes to cell with location=adr
  168. popx
  169. ret
  170. ;ddddddddddddddddddddddddddddddddddddddddddddddddddd
  171.  
  172. cstore_1: ;classic c!= "store"(adr 8-bitnum --) . 8 bit Num is now at cell adr.
  173. header store_1,2,"c!"
  174. cstore:
  175. mypop r16 ;there goes the num. Just 8 bits at this stage.
  176. pushx
  177. mypop2 xh,xl ;there goes the address
  178. st x+,r16
  179. ; st x,r17 ;num goes to cell with location=adr
  180. popx
  181. ret
  182. ;------------------------------------
  183.  
  184. star_1: ;classic 16*16 mulitply (n n -- n*n)
  185. header cstore_1,1,"*"
  186. star:
  187. mypop2 r17,r16
  188. mypop2 r19,r18 ;now have both numbers in r16..r19
  189. rcall mpy16s ; multiply them. Result in r18..r21. Overflow in r20,21
  190. mypush2 r18,r19
  191. ret
  192. ;-----------------------------------------
  193.  
  194. slashMod_1: ;classic /MOD (n m -- n/m rem)
  195. header star_1,4,"/mod"
  196. slashMod:
  197. mypop2 r19,r18 ; that's m
  198. mypop2 r17,r16 ;that's n
  199. rcall div16s ;the the 16 by 16 bit divsion
  200. mypush2 r16,r17 ;answer ie n/m
  201. mypush2 r14,r15 ;remainder
  202. ret
  203. ;dddddddddddddddddddddddddddddddddddddddddddd
  204.  
  205. plus_1: ;classic + ( n n -- n+n)
  206. header slashMod_1,1,"+"
  207. plus:
  208. mypop2 r17,r16
  209. mypop2 r19,r18
  210. clc
  211. add r16,r18
  212. adc r17,r19
  213. mypush2 r16,r17
  214. ret
  215. ;--
  216.  
  217. minus_1: ;classic - ( n m -- n-m)
  218. header plus_1,1,"-"
  219. minus:
  220. mypop2 r19,r18
  221. mypop2 r17,r16
  222. clc
  223. sub r16,r18
  224. sbc r17,r19
  225. mypush2 r16,r17
  226. ret
  227. ;dddddddddddddddddddddddddddddddddddddddddd
  228.  
  229. pstore_1: ;expects eg. 0003 PORTB P! etc, "output 3 via PORTB"
  230. header minus_1,2, "p!"
  231. pstore:
  232. mypopb ;get rid of PORTB number, not used for tiny85, just one port
  233. mypopa ; this is used. it's eg the 003 = R16 above
  234. out PORTB,r16
  235. ret
  236. ;ddddddddddddddddddddddddd
  237. LATEST:
  238. portblabel_1:
  239. header pstore_1,5,"PORTB" ; note caps just a filler that point 0b in stack for dropping
  240. portblabel:
  241. ; Extend later on to include perhaps other ports
  242. ; one:
  243. ; rcall stackme
  244.  
  245. rcall stackme_2
  246. .db $0b, 00
  247. ret
  248. ;---------------------
  249. HERE:
  250.  
  251.  
  252.  
  253.  
  254.  
  255.  
  256.  
  257.  
  258.  
  259.  
  260.  
  261.  
  262.  
  263.  
  264. ;-------------------------------------------------
  265. stackme_2: ;stacks on my stack next 16bit num. Address of 16bit number is on SP-stack
  266. ; Used like this stackme_2 0034. Puts 0034 on myStack and increments past number on return stack.
  267. pop r17
  268. pop r16 ; they now contain eg 0x0804 which contain the 16bit num
  269. movw zl,r16 ;z now points to cell that cobtains the number
  270. clc
  271. rol zl
  272. rol zh ;double word address for z. lpm coming up
  273.  
  274.  
  275.  
  276. lpm r16,z+
  277. lpm r17,z+ ;now have 16bit number in r16,17
  278.  
  279. st y+,r16
  280. st y+, r17 ;mystack now contains the number
  281.  
  282. clc
  283. ror zh
  284. ror zl ;halve the z pointer to step past the number to return at the right place
  285.  
  286. push zl
  287. push zh
  288.  
  289. ret
  290.  
  291.  
  292.  
  293. ;====================================================================================================
  294.  
  295. .ORG 0
  296. rjmp start
  297. typein: .db " one 0003 PORTB p! a298 B29A -", 0x0d
  298.  
  299. ;stackme dropx onex stackme swap drop",0x0d
  300. start:
  301. ldi r16, low(RAMEND)
  302. out SPL, r16
  303. ldi r16,high(RAMEND)
  304. out SPH, r16
  305.  
  306. ldi YL,low(myStackStart)
  307. ldi YH,high(myStackStart)
  308.  
  309. ;rjmp test_interpretLine
  310. ;rjmp test_cfetch
  311. ;rjmp test_store
  312. ;rjmp test_cstore
  313. ;rjmp test_mpy16s
  314. ;rjmp test_mpy16s0
  315. ;rjmp test_star
  316. ;rjmp test_div16s
  317. ;rjmp test_slashMod
  318. ;rjmp test_Hex4ToBin2
  319. rjmp test_interpretLine
  320.  
  321. rjmp start
  322.  
  323. getline0: ;force a line into buf1 via flash string. Simulates GETLINE
  324. ldi zl, low(typein<<1)
  325. ldi zh, high(typein<<1)
  326. ldi xl, low(buf1)
  327. ldi xh, high(buf1)
  328. type0:
  329. lpm r16,Z+
  330. st x+,r16
  331. cpi r16,0x0d ;have we got to the end of the line?
  332. brne type0
  333. ret
  334. ;--------------------------------------------
  335. ;WORD gets x to point to start of word (copy in w=r24,25) with the length in len = r20
  336. ;assume word points to somewhere in buf1. Should advance thru spaces=0x20 to first real char
  337. word: ;maybe give it a header later
  338. ld r16,x+ ;get char
  339. ld SECONDLETTER, x ;for debugging
  340.  
  341. cpi r16,0x20 ;is it a space?
  342. breq word ;if so get next char
  343. ;if here we're point to word start. so save this adr in w
  344. mov r24,xl
  345. mov r25,xh ;wordstart now saved in w
  346.  
  347.  
  348. clr r20 ;length initially 0
  349. nextchar:
  350. inc r20 ;r20 = word length
  351. ld r16,x+ ;get next char
  352. cpi r16,0x20
  353. brne nextchar
  354. dec r24 ;adjust start of word
  355. ;if here we've found a word.Starting at w length in r20.x points to space just past word
  356. ret
  357. ;----------------------------------------
  358.  
  359. 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.
  360. ; and the word in buf1 is pointed to by w=r24,25. len = r20. Z on entry points to the link. Needs +2 to
  361. lpm r23,z+
  362. lpm r22,z+ ;store next link in v=r22,23. z now points to len byte
  363.  
  364. startc:
  365. push r20 ;save length
  366. lpm r16,Z+ ;length of dictionary word, first entry now in r16
  367. cp r16,r20 ;same lengths?
  368. brne outcom ;not = so bail out
  369. ;if here the words are the same length, what about the rest of the chars.First get x to point to word.
  370. mov xl,r24
  371. mov xh,r25 ;x now point to start of buf1 word
  372. upcom:
  373. lpm r16,z+
  374. ld r17,x+ ;get one corresponding char from each word
  375. cp r16,r17 ;same word?
  376. brne outcom ;bail out if chars are different
  377. dec r20 ;count chars
  378. brne upcom ;still matching and not finished so keep going
  379. ;if here r20 is 0 so match must have been perfect so FOUND = 1
  380. clr FOUND
  381. inc FOUND
  382. outcom:
  383. pop r20 ;get old lngth of buf1 word back
  384. ret
  385. ;-------------------------------------------
  386. jmpNextWord: ;go to next word in the dictionary. Assume v=r22,23 contains next link word(not byte)
  387. ; and w = r24,25 contains RAM word start with len in r20
  388. ;exit with z pointing to next word ready for next COMPARE.
  389. clc
  390. rol r22
  391. rol r23 ;above 3 instructions change word address into byte address by doubling
  392. movw r30,r22 ;z now points to next word
  393. ret
  394. ;-----------------------------------------
  395.  
  396. doLatest: ;set up so first jump in dictionary is to top=LATEST and other flags set up.
  397. ldi vl, low(LATEST)
  398. ldi vh, high(LATEST)
  399. clr FOUND
  400. clr BOTTOM ;not yet found the match, not yet at the bottom. Either will stop search.
  401. clr STOP ;keep parsing words til this goes to a 1
  402. ret
  403. ;---------------------------------------------
  404. interpretLine: ;given line of words in buf one, search for words one by one. Don't do code
  405. ; or compile at this stage, just find and report that and go into next one.
  406. rcall getline0 ;change later to real getline via terminal
  407. rcall pasteEOL
  408. ldi xl, low(buf1)
  409. ldi xh,high(buf1) ;last 3 statemnts are done onece. Now the main loop.
  410. clr FOUNDCOUNTER ;counts finds in line parsing.
  411.  
  412. nextWord:
  413. tst STOP
  414. brne stopLine
  415. rcall word
  416. rcall findWord ;not done yet
  417. rcall dealWithWord ;go and run code STATE=0, or compile (STATE =1).{ c0de, comp1le}
  418. rjmp nextWord
  419. stopLine:
  420. ret
  421. ;-----------------------------------------------------------------
  422. findWord:
  423. rcall doLatest
  424. upjmpf:
  425. rcall jmpNextWord
  426. rcall compare
  427. tst FOUND
  428. brne stopsearchf ;if last compare got a match (FOUND=1) then stop searching
  429. tst vl
  430. brne upjmpf ;if v=0000 then we've hit the bottom of the dictionary
  431. tst vh
  432. brne upjmpf ;not found and not at bottom so keep going
  433. ;if here FOUND =0, ie no match yet and we've hit the bottom of the dictionary
  434. clr BOTTOM
  435. inc BOTTOM ;exit with FOUND=0 and BOTTOM =1
  436. stopsearchf: nop
  437. ret
  438. ;----------------------------
  439. test_interpretLine:
  440. rcall interpretLine
  441. til: rjmp til ;** with r24 pointing to 'S' and FOUND = r15 =1
  442. ;------------------------------
  443. dealWithWord: ;come here when it's time to compile or run code
  444. ;Good debugging spot. Enter here with Z pointing to CFA of word found. Y points to myStack. X points to just
  445. ; 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
  446. ; to the next word in dic. Either just below the found word or 0000 if we get to the bottome with no match
  447. ;
  448. nop
  449. tst FOUND
  450. breq notfound
  451. inc FOUNDCOUNTER
  452.  
  453. ;want to hop over filler bytes,0's added to keep codes on even byte boundaries
  454. ; so if r30 is odd at this stage inc it. odd is lsbit = 1.
  455. sbrs r30,0 ;skip next instruction if final bit lsb = 1
  456. rjmp downdw
  457. ;if here lsb = 1 so we're on a padding byte and have to add 1 to get to a 2 byte boundary
  458. inc r30
  459. brcc downdw
  460. inc r31 ;add one to z before converting to bytes
  461.  
  462. downdw:
  463. clc
  464. ror zh
  465. ror zl ;put z back into word values
  466.  
  467.  
  468. rcall executeCode
  469.  
  470.  
  471.  
  472. .MESSAGE "Word found"
  473. rjmp outdww
  474. notfound:
  475. nop
  476. ; .MESSAGE "Word not found"
  477. ; clr STOP
  478. ; inc STOP ;stop parsing line
  479. rcall numberh ; word not in dict so must be a number? Form = HHHH
  480. ;now have to add 3 to x so it points past this word ready not next one
  481. clc
  482. inc r26
  483. inc r26
  484. inc r26
  485. brcc outdww
  486. inc r27 ;but only if overflow
  487. nop
  488. outdww:
  489. ret ;with STOP =1 in not a number
  490. ;------------------------------------------------------------------------
  491. pasteEOL: ;when a line of text is TYPEd into buf1 it should end with CR=$0d. This gets replaced with ]}, a
  492. ; special end of line word. When the word is invoked it casues a QUIT back to the waiting for input stage.
  493. ; Start at buf1 start and inspect each char for a $0D. When found replace with a "$20 S $20 "
  494. ldi xl, low(buf1)
  495. ldi xh, high(buf1) ;pnt to start of buffer
  496. clr r17
  497. nxtChar:
  498. inc r17 ;r17 is counter. Bail out when r17 > BUF1LENGTH
  499. cpi r17, BUF1LENGTH -4
  500. breq outProb
  501. ld r16, x+
  502. cpi r16, $0d
  503. brne nxtChar
  504. ;if here we've found a $0d in buf1 before the end, so replace with an EOL token. x points to just after it.
  505. ldi r16,$20
  506. st -x, r16 ;back up. Then go forward.
  507. ; ldi r16, ']'
  508. st x+, r16
  509. ldi r16,'S'
  510. st x+, r16
  511. ; ldi r16, '}'
  512. ; st x+, r16
  513. ldi r16, $20
  514. st x, r16
  515. rjmp outpel
  516.  
  517.  
  518. outProb:
  519. nop
  520. .MESSAGE "Couldn't find $0d"
  521. outpel:
  522. ret
  523.  
  524. ;-------------------------------------
  525. executeCode: ;with Z pointing to cfa. Not sure whether to jmp or call
  526.  
  527. ijmp
  528. ret
  529. ;---------------------------------------
  530. test_fetch: ;do run thru of @
  531. rcall getline0 ;change later to real getline via terminal
  532. rcall pasteEOL
  533. ldi xl, low(buf1)
  534. ldi xh,high(buf1) ;last 3 statemnts are done onece. Now the main loop.
  535.  
  536. ldi r16,$62
  537. mypush r16
  538. ldi r16,$0
  539. mypush r16 ;should now have adr $0062 on mystack
  540. rcall fetch
  541. tf1:
  542. rjmp tf1
  543. ;---------------------------------
  544. test_cfetch: ;do run thru of @
  545. rcall getline0 ;change later to real getline via terminal
  546. rcall pasteEOL
  547. ldi xl, low(buf1)
  548. ldi xh,high(buf1) ;last 3 statemnts are done onece. Now the main loop.
  549.  
  550. ldi r16,$62
  551. mypush r16
  552. ldi r16,$0
  553. mypush r16 ;should now have adr $62 on mystack
  554. rcall cfetch
  555. tcf1:
  556. rjmp tcf1
  557. ;----------------------------
  558. test_store:
  559. rcall getline0 ;change later to real getline via terminal
  560. rcall pasteEOL
  561. ldi xl, low(buf1)
  562. ldi xh,high(buf1) ;last 3 statemnts are done onece. Now the main loop.
  563. ldi r16,$62
  564. ldi r17,$0
  565. mypush2 r16,r17 ;should now have adr $62 on mystack
  566. ldi r16, $AB
  567. ldi r17, $CD
  568. mypush2 r16,r17 ;now have $ABCD on mystack
  569. rcall store
  570. ts1:
  571. rjmp ts1
  572. ;------------------------
  573. test_cstore:
  574. rcall getline0 ;change later to real getline via terminal
  575. rcall pasteEOL
  576. ldi xl, low(buf1)
  577. ldi xh,high(buf1) ;last 3 statemnts are done onece. Now the main loop.
  578. ldi r16,$62
  579. ldi r17,$0
  580. mypush2 r16,r17 ;should now have adr $62 on mystack
  581. ldi r16, $AB
  582. ; ldi r17, $CD
  583. mypush r16 ;now have $ABCD on mystack
  584. rcall cstore
  585.  
  586. ts11:
  587. rjmp ts11
  588. ;Now put arith routines here. Are from AVR200. Just using 16*16 for * but get 32bit result.
  589.  
  590.  
  591. ;***************************************************************************
  592. ;*
  593. ;* "mpy16s" - 16x16 Bit Signed Multiplication
  594. ;*
  595. ;* This subroutine multiplies signed the two 16-bit register variables
  596. ;* mp16sH:mp16sL and mc16sH:mc16sL.
  597. ;* The result is placed in m16s3:m16s2:m16s1:m16s0.
  598. ;* The routine is an implementation of Booth's algorithm. If all 32 bits
  599. ;* in the result are needed, avoid calling the routine with
  600. ;* -32768 ($8000) as multiplicand
  601. ;*
  602. ;* Number of words :16 + return
  603. ;* Number of cycles :210/226 (Min/Max) + return
  604. ;* Low registers used :None
  605. ;* High registers used :7 (mp16sL,mp16sH,mc16sL/m16s0,mc16sH/m16s1,
  606. ;* m16s2,m16s3,mcnt16s)
  607. ;*
  608. ;***************************************************************************
  609.  
  610. ;***** Subroutine Register Variables
  611.  
  612. .def mc16sL =r16 ;multiplicand low byte
  613. .def mc16sH =r17 ;multiplicand high byte
  614. .def mp16sL =r18 ;multiplier low byte
  615. .def mp16sH =r19 ;multiplier high byte
  616. .def m16s0 =r18 ;result byte 0 (LSB)
  617. .def m16s1 =r19 ;result byte 1
  618. .def m16s2 =r20 ;result byte 2
  619. .def m16s3 =r21 ;result byte 3 (MSB)
  620. .def mcnt16s =r22 ;loop counter
  621.  
  622. ;***** Code
  623. mpy16s: clr m16s3 ;clear result byte 3
  624. sub m16s2,m16s2 ;clear result byte 2 and carry
  625. ldi mcnt16s,16 ;init loop counter
  626. m16s_1: brcc m16s_2 ;if carry (previous bit) set
  627. add m16s2,mc16sL ; add multiplicand Low to result byte 2
  628. adc m16s3,mc16sH ; add multiplicand High to result byte 3
  629. m16s_2: sbrc mp16sL,0 ;if current bit set
  630. sub m16s2,mc16sL ; sub multiplicand Low from result byte 2
  631. sbrc mp16sL,0 ;if current bit set
  632. sbc m16s3,mc16sH ; sub multiplicand High from result byte 3
  633. asr m16s3 ;shift right result and multiplier
  634. ror m16s2
  635. ror m16s1
  636. ror m16s0
  637. dec mcnt16s ;decrement counter
  638. brne m16s_1 ;if not done, loop more
  639. ret
  640. ;----------------------------------------------------------
  641. ;***** Multiply Two Signed 16-Bit Numbers (-12345*(-4321))
  642. test_mpy16s:
  643. ldi mc16sL,low(-12345)
  644. ldi mc16sH,high(-12345)
  645. ldi mp16sL,low(-4321)
  646. ldi mp16sH,high(-4321)
  647. rcall mpy16s ;result: m16s3:m16s2:m16s1:m16s0
  648. ;=$032df219 (53,342,745)
  649. tmpy: rjmp tmpy
  650.  
  651. test_mpy16s0:
  652. ldi mc16sL,low(123)
  653. ldi mc16sH,high(123)
  654. ldi mp16sL,low(147)
  655. ldi mp16sH,high(147)
  656. rcall mpy16s ;result: m16s3:m16s2:m16s1:m16s0
  657. tmpy0: rjmp tmpy0
  658. ;-----------------------
  659. test_star:
  660. ldi r16,-$7b
  661. mypush r16
  662. ldi r16,$00
  663. mypush r16 ;that's decimal 123 on stack
  664. ldi r16,$93
  665. mypush r16
  666. ldi r16,$00
  667. mypush r16 ; and thats dec'147
  668. rcall star
  669. tsr: rjmp tsr
  670.  
  671. ;--------------------------
  672. ;***************************************************************************
  673. ;*
  674. ;* "div16s" - 16/16 Bit Signed Division
  675. ;*
  676. ;* This subroutine divides signed the two 16 bit numbers
  677. ;* "dd16sH:dd16sL" (dividend) and "dv16sH:dv16sL" (divisor).
  678. ;* The result is placed in "dres16sH:dres16sL" and the remainder in
  679. ;* "drem16sH:drem16sL".
  680. ;*
  681. ;* Number of words :39
  682. ;* Number of cycles :247/263 (Min/Max)
  683. ;* Low registers used :3 (d16s,drem16sL,drem16sH)
  684. ;* High registers used :7 (dres16sL/dd16sL,dres16sH/dd16sH,dv16sL,dv16sH,
  685. ;* dcnt16sH)
  686. ;*
  687. ;***************************************************************************
  688.  
  689. ;***** Subroutine Register Variables
  690.  
  691. .def d16s =r13 ;sign register
  692. .def drem16sL=r14 ;remainder low byte
  693. .def drem16sH=r15 ;remainder high byte
  694. .def dres16sL=r16 ;result low byte
  695. .def dres16sH=r17 ;result high byte
  696. .def dd16sL =r16 ;dividend low byte
  697. .def dd16sH =r17 ;dividend high byte
  698. .def dv16sL =r18 ;divisor low byte
  699. .def dv16sH =r19 ;divisor high byte
  700. .def dcnt16s =r20 ;loop counter
  701.  
  702. ;***** Code
  703.  
  704. div16s: mov d16s,dd16sH ;move dividend High to sign register
  705. eor d16s,dv16sH ;xor divisor High with sign register
  706. sbrs dd16sH,7 ;if MSB in dividend set
  707. rjmp d16s_1
  708. com dd16sH ; change sign of dividend
  709. com dd16sL
  710. subi dd16sL,low(-1)
  711. sbci dd16sL,high(-1)
  712. d16s_1: sbrs dv16sH,7 ;if MSB in divisor set
  713. rjmp d16s_2
  714. com dv16sH ; change sign of divisor
  715. com dv16sL
  716. subi dv16sL,low(-1)
  717. sbci dv16sL,high(-1)
  718. d16s_2: clr drem16sL ;clear remainder Low byte
  719. sub drem16sH,drem16sH;clear remainder High byte and carry
  720. ldi dcnt16s,17 ;init loop counter
  721.  
  722. d16s_3: rol dd16sL ;shift left dividend
  723. rol dd16sH
  724. dec dcnt16s ;decrement counter
  725. brne d16s_5 ;if done
  726. sbrs d16s,7 ; if MSB in sign register set
  727. rjmp d16s_4
  728. com dres16sH ; change sign of result
  729. com dres16sL
  730. subi dres16sL,low(-1)
  731. sbci dres16sH,high(-1)
  732. d16s_4: ret ; return
  733. d16s_5: rol drem16sL ;shift dividend into remainder
  734. rol drem16sH
  735. sub drem16sL,dv16sL ;remainder = remainder - divisor
  736. sbc drem16sH,dv16sH ;
  737. brcc d16s_6 ;if result negative
  738. add drem16sL,dv16sL ; restore remainder
  739. adc drem16sH,dv16sH
  740. clc ; clear carry to be shifted into result
  741. rjmp d16s_3 ;else
  742. d16s_6: sec ; set carry to be shifted into result
  743. rjmp d16s_3
  744.  
  745. ;-----------------------------------------------
  746.  
  747. test_div16s:
  748. ;***** Divide Two Signed 16-Bit Numbers (-22,222/10)
  749. ldi dd16sL,low(-22222)
  750. ldi dd16sH,high(-22222)
  751. ldi dv16sL,low(10)
  752. ldi dv16sH,high(10)
  753. rcall div16s ;result: $f752 (-2222)
  754. ;remainder: $0002 (2)
  755.  
  756. forever:rjmp forever
  757. ;----------------------------------
  758. test_slashMod:
  759. ldi r16,$12
  760. mypush r16
  761. ldi r16,$34
  762. mypush r16
  763. ldi r16,$56 ;NB this is $3412 not $1234
  764. mypush r16
  765. ldi r16,$00
  766. mypush r16
  767. rcall slashMod ;$3412 / $56 = $9b rem 0 works
  768. tslm: rjmp tslm
  769.  
  770. ;---------------------------------------
  771. ;From http://www.avr-asm-tutorial.net/avr_en/calc/CONVERT.html#hex2bin
  772. ; Hex4ToBin2
  773. ; converts a 4-digit-hex-ascii to a 16-bit-binary
  774. ; In: Z points to first digit of a Hex-ASCII-coded number
  775. ; Out: T-flag has general result:
  776. ; T=0: rBin1H:L has the 16-bit-binary result, Z points
  777. ; to the first digit of the Hex-ASCII number
  778. ; T=1: illegal character encountered, Z points to the
  779. ; first non-hex-ASCII character
  780. ; Used registers: rBin1H:L (result), R0 (restored after
  781. ; use), rmp
  782. ; Called subroutines: Hex2ToBin1, Hex1ToBin1
  783.  
  784. .def rBin1H =r17
  785. .def rBin1L = r16
  786. .def rmp = r18
  787. ;
  788. Hex4ToBin2:
  789. clt ; Clear error flag
  790. rcall Hex2ToBin1 ; convert two digits hex to Byte
  791. brts Hex4ToBin2a ; Error, go back
  792. mov rBin1H,rmp ; Byte to result MSB
  793. rcall Hex2ToBin1 ; next two chars
  794. brts Hex4ToBin2a ; Error, go back
  795. mov rBin1L,rmp ; Byte to result LSB
  796. sbiw ZL,4 ; result ok, go back to start
  797. Hex4ToBin2a:
  798. ret
  799. ;
  800. ; Hex2ToBin1 converts 2-digit-hex-ASCII to 8-bit-binary
  801. ; Called By: Hex4ToBin2
  802. ;
  803. Hex2ToBin1:
  804. push R0 ; Save register
  805. rcall Hex1ToBin1 ; Read next char
  806. brts Hex2ToBin1a ; Error
  807. swap rmp; To upper nibble
  808. mov R0,rmp ; interim storage
  809. rcall Hex1ToBin1 ; Read another char
  810. brts Hex2ToBin1a ; Error
  811. or rmp,R0 ; pack the two nibbles together
  812. Hex2ToBin1a:
  813. pop R0 ; Restore R0
  814. ret ; and return
  815. ;
  816. ; Hex1ToBin1 reads one char and converts to binary
  817. ;
  818. Hex1ToBin1:
  819. ld rmp,z+ ; read the char
  820. subi rmp,'0' ; ASCII to binary
  821. brcs Hex1ToBin1b ; Error in char
  822. cpi rmp,10 ; A..F
  823. brcs Hex1ToBin1c ; not A..F
  824. cpi rmp,$30 ; small letters?
  825. brcs Hex1ToBin1a ; No
  826. subi rmp,$20 ; small to capital letters
  827. Hex1ToBin1a:
  828. subi rmp,7 ; A..F
  829. cpi rmp,10 ; A..F?
  830. brcs Hex1ToBin1b ; Error, is smaller than A
  831. cpi rmp,16 ; bigger than F?
  832. brcs Hex1ToBin1c ; No, digit ok
  833. Hex1ToBin1b: ; Error
  834. sbiw ZL,1 ; one back
  835. set ; Set flag
  836. Hex1ToBin1c:
  837. ret ; Return
  838. ;--------------------------------------
  839. test_Hex4ToBin2:
  840. pushz
  841. ldi zl,$60
  842. clr zh ;z now points to start of buf1
  843. ldi r16,'0'
  844. st z+,r16
  845. ldi r16,'f'
  846. st z+,r16
  847. ldi r16,'2'
  848. st z+,r16
  849. ldi r16,'3'
  850. st z+,r16
  851. ldi zl,$60
  852. clr zh ;z now points back to start of buf1
  853. rcall Hex4ToBin2
  854. popz
  855. th4: rjmp th4
  856. ;-------------------------------------
  857. numberh: ;word not in dictionary. Try to convert it to hex.
  858. pushz ;algorithm uses z, pity
  859. movw zl,r24 ;r4,25 = w holds start of current word
  860. ;z now points eg to '12ab'start. If t=0 then it coverts to real hex
  861. rcall hex4ToBin2 ;try to convert
  862. ;above call needs 4 hex digits to emerge with t=0 and binary in r16,17
  863. ;want this. If t=0 stack r16,17 and carry on interpreting, else emerge with
  864. ; t=1 and zpointing to first problem char
  865. brtc gotHex
  866. ; if here there's a problem that z is pointing to. Bail out of interpret line
  867. clr STOP
  868. inc STOP
  869. rjmp outnh
  870.  
  871. gotHex: ;sucess.Real hex in r16,17
  872. mypush2 r16,r17 ; so push num onto mystack
  873. outnh:
  874. popz ; but will it be pointing to "right"place in buf1? Yes now OK
  875.  
  876. ret
  877. ; numberh not working fully, ie doesn't point to right place after action.
  878. ; also no action if not a number? DONE better save this first.
  879. ;---------------------------------
Advertisement
Add Comment
Please, Sign In to add comment