prjbrook

forth85_07. *, /MOD

Jul 15th, 2014
243
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.75 KB | None | 0 0
  1. ;http://www.avr-asm-tutorial.net/avr_en/calc/CONVERT.html#hex2bin working on now
  2. ;this is forth85_07.
  3. ; next do * and /MOD. Find code on net.Gort * and /MOD from AVR200.
  4. ; above seems to be going OK
  5.  
  6. .NOLIST
  7. .include "tn85def.inc"
  8. .LIST
  9. .LISTMAC ;sometimes macro code gets in way of clarity in listing
  10. .MACRO header
  11. .db high(@0), low(@0), @1, @2
  12. .ENDMACRO
  13. .MACRO mypop
  14. ld @0,-y
  15. .ENDMACRO
  16. .MACRO mypush
  17. st y+, @0
  18. .ENDMACRO
  19. .MACRO mypop2
  20. mypop @0
  21. mypop @1
  22. .ENDMACRO
  23. .MACRO mypush2
  24. mypush @0
  25. mypush @1
  26. .ENDMACRO
  27. .MACRO pushx
  28. push xl
  29. push xh
  30. .ENDMACRO
  31. .MACRO popx
  32. pop xh
  33. pop xl
  34. .ENDMACRO
  35.  
  36.  
  37. .def FOUND = r15 ;if found=1 we have a match of Ram word on dictionary
  38. .def BOTTOM = r14 ;have hit the bottom of the dict and not found a match
  39. .def STOP = r13 ;stop interpreting line of words
  40. .def STATE = r12
  41. .def FOUNDCOUNTER = r11 ;dealWithWord clicks this if found =1. Counts successful finds in dictionary.
  42. .def SECONDLETTER =r10 ;helpful for debugging
  43. .def vl = r22
  44. .def vh = r23 ; u,v,w,x,y,z are all pointers
  45. .DSEG
  46. .ORG 0x60
  47.  
  48. ;consts: .DB "jksdafhsdf",8, 255, 0b01010101, -128, 0xaa
  49. .equ BUF1LENGTH = 64
  50.  
  51. buf1: .byte BUF1LENGTH
  52. buf2: .byte 64 ;could have third buffer?
  53. varSpace: .byte 64 ;might need more than 32 variables
  54. ;.org 0x1E0
  55. myStackStart: .byte 64
  56.  
  57. .cseg
  58. .ORG 0x800 ;dictionary starts at 4K (2K words) mark
  59. ;----------------------------------------------------
  60. one_1:
  61. .db 0,0,3, "one" ;code for one
  62. one:
  63. ; rcall stackme
  64. rcall stackme_2
  65. .db 01, 00
  66. ret
  67. ;----------------------------------------------
  68. two_1:
  69. header one_1, 3, "two"
  70. two:
  71. rcall stackme_2
  72. .db 02,00
  73. ret
  74. ;------------------------------------------
  75. dup_1:
  76. header two_1,3,"dup"
  77. dup:
  78. mypop r17
  79. mypop r16
  80. mypush r16
  81. mypush r17
  82. mypush r16
  83. mypush r17
  84.  
  85. ret
  86. ;-------------------------------------------
  87. drop_1:
  88. header dup_1,4,"drop"
  89. drop:
  90. mypop r17
  91. mypop r16 ;TODO what if stack pointer goes thru floor?
  92. ret
  93. ;----------------------------------
  94. swapp_1: ;twp p's becasue assembler recognizes avr opcode swap
  95. header drop_1,5, "swapp"
  96. swapp:
  97. mypop2 r17,r16
  98. mypop2 r19,r18
  99. mypush2 r16,r17
  100. mypush2 r18,r19
  101. ret
  102.  
  103.  
  104. ;-------------------------------------------------
  105. ;shift this later
  106.  
  107. S_1:
  108. ;the EOL token that gets put into end of buf1 to stop parsing
  109. header swapp_1,1,"S"
  110. S:
  111. clr STOP
  112. inc STOP ;set time-to-quit flag
  113. ret
  114. ;------------------------------------------
  115.  
  116. fetch_1: ;doesn't like label = @-1
  117. ;classic fetch. (adr -- num). Only in RAM
  118. header S_1,1,"@"
  119. fetch:
  120. pushx ;going to use x to point so better save
  121. mypop xh
  122. mypop xl
  123. ld r16,x+
  124. ld r17,x
  125. mypush r16
  126. mypush r17 ; and put them on my stack
  127. popx ;return with x intact and RAM val on my stack
  128. ret
  129. ;dddddddddddddddddddddddddddddddddddddddddddddddd
  130.  
  131. cfetch_1: ;doesn't like label = c@-1
  132. ;classic fetch. (adr -- num). Only in RAM. Do I want y to advance just one byte on mystack
  133. header fetch_1,2,"c@"
  134. cfetch:
  135. pushx ;going to use x to point so better save
  136. mypop xh
  137. mypop xl
  138. ld r16,x+
  139. mypush r16
  140. popx ;return with x intact and RAM val on my stack
  141. ret
  142. ;dddddddddddddddddddddddddddddddddddddddddddddddd
  143.  
  144. store_1: ;classic != "store"(adr num --) . Num is now at cell adr.
  145. header cfetch_1,1,"!"
  146. store:
  147. mypop2 r17,r16 ;there goes the num
  148. pushx
  149. mypop2 xh,xl ;there goes the address
  150. st x+,r16
  151. st x,r17 ;num goes to cell with location=adr
  152. popx
  153. ret
  154. ;ddddddddddddddddddddddddddddddddddddddddddddddddddd
  155.  
  156. cstore_1: ;classic c!= "store"(adr 8-bitnum --) . 8 bit Num is now at cell adr.
  157. header store_1,2,"c!"
  158. cstore:
  159. mypop r16 ;there goes the num. Just 8 bits at this stage.
  160. pushx
  161. mypop2 xh,xl ;there goes the address
  162. st x+,r16
  163. ; st x,r17 ;num goes to cell with location=adr
  164. popx
  165. ret
  166. ;------------------------------------
  167.  
  168. star_1: ;classic 16*16 mulitply (n n -- n*n)
  169. header cstore_1,1,"*"
  170. star:
  171. mypop2 r17,r16
  172. mypop2 r19,r18 ;now have both numbers in r16..r19
  173. rcall mpy16s ; multiply them. Result in r18..r21. Overflow in r20,21
  174. mypush2 r18,r19
  175. ret
  176. ;-----------------------------------------
  177. LATEST:
  178. slashMod_1: ;classic /MOD (n m -- n/m rem)
  179. header star_1,4,"/mod"
  180. slashMod:
  181. mypop2 r19,r18 ; that's m
  182. mypop2 r17,r16 ;that's n
  183. rcall div16s ;the the 16 by 16 bit divsion
  184. mypush2 r16,r17 ;answer ie n/m
  185. mypush2 r14,r15 ;remainder
  186. ret
  187.  
  188.  
  189.  
  190.  
  191.  
  192.  
  193. ;-------------------------------------------------
  194. stackme_2: ;stacks on my stack next 16bit num. Address of 16bit number is on SP-stack
  195. ; Used like this stackme_2 0034. Puts 0034 on myStack and increments past number on return stack.
  196. pop r17
  197. pop r16 ; they now contain eg 0x0804 which contain the 16bit num
  198. movw zl,r16 ;z now points to cell that cobtains the number
  199. clc
  200. rol zl
  201. rol zh ;double word address for z. lpm coming up
  202.  
  203.  
  204.  
  205. lpm r16,z+
  206. lpm r17,z+ ;now have 16bit number in r16,17
  207.  
  208. st y+,r16
  209. st y+, r17 ;mystack now contains the number
  210.  
  211. clc
  212. ror zh
  213. ror zl ;halve the z pointer to step past the number to return at the right place
  214.  
  215. push zl
  216. push zh
  217.  
  218. ret
  219.  
  220.  
  221.  
  222. ;====================================================================================================
  223.  
  224. .ORG 0
  225. rjmp start
  226. typein: .db " one two dup drop swapp ", 0x0d
  227.  
  228. ;stackme dropx onex stackme swap drop",0x0d
  229. start:
  230. ldi r16, low(RAMEND)
  231. out SPL, r16
  232. ldi r16,high(RAMEND)
  233. out SPH, r16
  234.  
  235. ldi YL,low(myStackStart)
  236. ldi YH,high(myStackStart)
  237.  
  238. ;rjmp test_interpretLine
  239. ;rjmp test_cfetch
  240. ;rjmp test_store
  241. ;rjmp test_cstore
  242. ;rjmp test_mpy16s
  243. ;rjmp test_mpy16s0
  244. ;rjmp test_star
  245. ;rjmp test_div16s
  246. rjmp test_slashMod
  247.  
  248. rjmp start
  249.  
  250. getline0: ;force a line into buf1 via flash string. Simulates GETLINE
  251. ldi zl, low(typein<<1)
  252. ldi zh, high(typein<<1)
  253. ldi xl, low(buf1)
  254. ldi xh, high(buf1)
  255. type0:
  256. lpm r16,Z+
  257. st x+,r16
  258. cpi r16,0x0d ;have we got to the end of the line?
  259. brne type0
  260. ret
  261. ;--------------------------------------------
  262. ;WORD gets x to point to start of word (copy in w=r24,25) with the length in len = r20
  263. ;assume word points to somewhere in buf1. Should advance thru spaces=0x20 to first real char
  264. word: ;maybe give it a header later
  265. ld r16,x+ ;get char
  266. ld SECONDLETTER, x ;for debugging
  267.  
  268. cpi r16,0x20 ;is it a space?
  269. breq word ;if so get next char
  270. ;if here we're point to word start. so save this adr in w
  271. mov r24,xl
  272. mov r25,xh ;wordstart now saved in w
  273.  
  274.  
  275. clr r20 ;length initially 0
  276. nextchar:
  277. inc r20 ;r20 = word length
  278. ld r16,x+ ;get next char
  279. cpi r16,0x20
  280. brne nextchar
  281. dec r24 ;adjust start of word
  282. ;if here we've found a word.Starting at w length in r20.x points to space just past word
  283. ret
  284. ;----------------------------------------
  285.  
  286. 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.
  287. ; and the word in buf1 is pointed to by w=r24,25. len = r20. Z on entry points to the link. Needs +2 to
  288. lpm r23,z+
  289. lpm r22,z+ ;store next link in v=r22,23. z now points to len byte
  290.  
  291. startc:
  292. push r20 ;save length
  293. lpm r16,Z+ ;length of dictionary word, first entry now in r16
  294. cp r16,r20 ;same lengths?
  295. brne outcom ;not = so bail out
  296. ;if here the words are the same length, what about the rest of the chars.First get x to point to word.
  297. mov xl,r24
  298. mov xh,r25 ;x now point to start of buf1 word
  299. upcom:
  300. lpm r16,z+
  301. ld r17,x+ ;get one corresponding char from each word
  302. cp r16,r17 ;same word?
  303. brne outcom ;bail out if chars are different
  304. dec r20 ;count chars
  305. brne upcom ;still matching and not finished so keep going
  306. ;if here r20 is 0 so match must have been perfect so FOUND = 1
  307. clr FOUND
  308. inc FOUND
  309. outcom:
  310. pop r20 ;get old lngth of buf1 word back
  311. ret
  312. ;-------------------------------------------
  313. jmpNextWord: ;go to next word in the dictionary. Assume v=r22,23 contains next link word(not byte)
  314. ; and w = r24,25 contains RAM word start with len in r20
  315. ;exit with z pointing to next word ready for next COMPARE.
  316. clc
  317. rol r22
  318. rol r23 ;above 3 instructions change word address into byte address by doubling
  319. movw r30,r22 ;z now points to next word
  320. ret
  321. ;-----------------------------------------
  322.  
  323. doLatest: ;set up so first jump in dictionary is to top=LATEST and other flags set up.
  324. ldi vl, low(LATEST)
  325. ldi vh, high(LATEST)
  326. clr FOUND
  327. clr BOTTOM ;not yet found the match, not yet at the bottom. Either will stop search.
  328. clr STOP ;keep parsing words til this goes to a 1
  329. ret
  330. ;---------------------------------------------
  331. interpretLine: ;given line of words in buf one, search for words one by one. Don't do code
  332. ; or compile at this stage, just find and report that and go into next one.
  333. rcall getline0 ;change later to real getline via terminal
  334. rcall pasteEOL
  335. ldi xl, low(buf1)
  336. ldi xh,high(buf1) ;last 3 statemnts are done onece. Now the main loop.
  337. clr FOUNDCOUNTER ;counts finds in line parsing.
  338.  
  339. nextWord:
  340. tst STOP
  341. brne stopLine
  342. rcall word
  343. rcall findWord ;not done yet
  344. rcall dealWithWord ;go and run code STATE=0, or compile (STATE =1).{ c0de, comp1le}
  345. rjmp nextWord
  346. stopLine:
  347. ret
  348. ;-----------------------------------------------------------------
  349. findWord:
  350. rcall doLatest
  351. upjmpf:
  352. rcall jmpNextWord
  353. rcall compare
  354. tst FOUND
  355. brne stopsearchf ;if last compare got a match (FOUND=1) then stop searching
  356. tst vl
  357. brne upjmpf ;if v=0000 then we've hit the bottom of the dictionary
  358. tst vh
  359. brne upjmpf ;not found and not at bottom so keep going
  360. ;if here FOUND =0, ie no match yet and we've hit the bottom of the dictionary
  361. clr BOTTOM
  362. inc BOTTOM ;exit with FOUND=0 and BOTTOM =1
  363. stopsearchf: nop
  364. ret
  365. ;----------------------------
  366. test_interpretLine:
  367. rcall interpretLine
  368. til: rjmp til ;**
  369. ;------------------------------
  370. dealWithWord: ;come here when it's time to compile or run code
  371. ;Good debugging spot. Enter here with Z pointing to CFA of word found. Y points to myStack. X points to just
  372. ; 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
  373. ; to the next word in dic. Either just below the found word or 0000 if we get to the bottome with no match
  374. ;
  375. nop
  376. tst FOUND
  377. breq notfound
  378. inc FOUNDCOUNTER
  379.  
  380. ;want to hop over filler bytes,0's added to keep codes on even byte boundaries
  381. ; so if r30 is odd at this stage inc it. odd is lsbit = 1.
  382. sbrs r30,0 ;skip next instruction if final bit lsb = 1
  383. rjmp downdw
  384. ;if here lsb = 1 so we're on a padding byte and have to add 1 to get to a 2 byte boundary
  385. inc r30
  386. brcc downdw
  387. inc r31 ;add one to z before converting to bytes
  388.  
  389. downdw:
  390. clc
  391. ror zh
  392. ror zl ;put z back into word values
  393.  
  394.  
  395. rcall executeCode
  396.  
  397.  
  398.  
  399. .MESSAGE "Word found"
  400. rjmp outdww
  401. notfound:
  402. .MESSAGE "Word not found"
  403. clr STOP
  404. inc STOP ;stop parsing line
  405. outdww:
  406. ret
  407. ;------------------------------------------------------------------------
  408. pasteEOL: ;when a line of text is TYPEd into buf1 it should end with CR=$0d. This gets replaced with ]}, a
  409. ; special end of line word. When the word is invoked it casues a QUIT back to the waiting for input stage.
  410. ; Start at buf1 start and inspect each char for a $0D. When found replace with a "$20 S $20 "
  411. ldi xl, low(buf1)
  412. ldi xh, high(buf1) ;pnt to start of buffer
  413. clr r17
  414. nxtChar:
  415. inc r17 ;r17 is counter. Bail out when r17 > BUF1LENGTH
  416. cpi r17, BUF1LENGTH -4
  417. breq outProb
  418. ld r16, x+
  419. cpi r16, $0d
  420. brne nxtChar
  421. ;if here we've found a $0d in buf1 before the end, so replace with an EOL token. x points to just after it.
  422. ldi r16,$20
  423. st -x, r16 ;back up. Then go forward.
  424. ; ldi r16, ']'
  425. st x+, r16
  426. ldi r16,'S'
  427. st x+, r16
  428. ; ldi r16, '}'
  429. ; st x+, r16
  430. ldi r16, $20
  431. st x, r16
  432. rjmp outpel
  433.  
  434.  
  435. outProb:
  436. nop
  437. .MESSAGE "Couldn't find $0d"
  438. outpel:
  439. ret
  440.  
  441. ;-------------------------------------
  442. executeCode: ;with Z pointing to cfa. Not sure whether to jmp or call
  443.  
  444. ijmp
  445. ret
  446. ;---------------------------------------
  447. test_fetch: ;do run thru of @
  448. rcall getline0 ;change later to real getline via terminal
  449. rcall pasteEOL
  450. ldi xl, low(buf1)
  451. ldi xh,high(buf1) ;last 3 statemnts are done onece. Now the main loop.
  452.  
  453. ldi r16,$62
  454. mypush r16
  455. ldi r16,$0
  456. mypush r16 ;should now have adr $0062 on mystack
  457. rcall fetch
  458. tf1:
  459. rjmp tf1
  460. ;---------------------------------
  461. test_cfetch: ;do run thru of @
  462. rcall getline0 ;change later to real getline via terminal
  463. rcall pasteEOL
  464. ldi xl, low(buf1)
  465. ldi xh,high(buf1) ;last 3 statemnts are done onece. Now the main loop.
  466.  
  467. ldi r16,$62
  468. mypush r16
  469. ldi r16,$0
  470. mypush r16 ;should now have adr $62 on mystack
  471. rcall cfetch
  472. tcf1:
  473. rjmp tcf1
  474. ;----------------------------
  475. test_store:
  476. rcall getline0 ;change later to real getline via terminal
  477. rcall pasteEOL
  478. ldi xl, low(buf1)
  479. ldi xh,high(buf1) ;last 3 statemnts are done onece. Now the main loop.
  480. ldi r16,$62
  481. ldi r17,$0
  482. mypush2 r16,r17 ;should now have adr $62 on mystack
  483. ldi r16, $AB
  484. ldi r17, $CD
  485. mypush2 r16,r17 ;now have $ABCD on mystack
  486. rcall store
  487. ts1:
  488. rjmp ts1
  489. ;------------------------
  490. test_cstore:
  491. rcall getline0 ;change later to real getline via terminal
  492. rcall pasteEOL
  493. ldi xl, low(buf1)
  494. ldi xh,high(buf1) ;last 3 statemnts are done onece. Now the main loop.
  495. ldi r16,$62
  496. ldi r17,$0
  497. mypush2 r16,r17 ;should now have adr $62 on mystack
  498. ldi r16, $AB
  499. ; ldi r17, $CD
  500. mypush r16 ;now have $ABCD on mystack
  501. rcall cstore
  502.  
  503. ts11:
  504. rjmp ts11
  505. ;Now put arith routines here. Are from AVR200. Just using 16*16 for * but get 32bit result.
  506.  
  507.  
  508. ;***************************************************************************
  509. ;*
  510. ;* "mpy16s" - 16x16 Bit Signed Multiplication
  511. ;*
  512. ;* This subroutine multiplies signed the two 16-bit register variables
  513. ;* mp16sH:mp16sL and mc16sH:mc16sL.
  514. ;* The result is placed in m16s3:m16s2:m16s1:m16s0.
  515. ;* The routine is an implementation of Booth's algorithm. If all 32 bits
  516. ;* in the result are needed, avoid calling the routine with
  517. ;* -32768 ($8000) as multiplicand
  518. ;*
  519. ;* Number of words :16 + return
  520. ;* Number of cycles :210/226 (Min/Max) + return
  521. ;* Low registers used :None
  522. ;* High registers used :7 (mp16sL,mp16sH,mc16sL/m16s0,mc16sH/m16s1,
  523. ;* m16s2,m16s3,mcnt16s)
  524. ;*
  525. ;***************************************************************************
  526.  
  527. ;***** Subroutine Register Variables
  528.  
  529. .def mc16sL =r16 ;multiplicand low byte
  530. .def mc16sH =r17 ;multiplicand high byte
  531. .def mp16sL =r18 ;multiplier low byte
  532. .def mp16sH =r19 ;multiplier high byte
  533. .def m16s0 =r18 ;result byte 0 (LSB)
  534. .def m16s1 =r19 ;result byte 1
  535. .def m16s2 =r20 ;result byte 2
  536. .def m16s3 =r21 ;result byte 3 (MSB)
  537. .def mcnt16s =r22 ;loop counter
  538.  
  539. ;***** Code
  540. mpy16s: clr m16s3 ;clear result byte 3
  541. sub m16s2,m16s2 ;clear result byte 2 and carry
  542. ldi mcnt16s,16 ;init loop counter
  543. m16s_1: brcc m16s_2 ;if carry (previous bit) set
  544. add m16s2,mc16sL ; add multiplicand Low to result byte 2
  545. adc m16s3,mc16sH ; add multiplicand High to result byte 3
  546. m16s_2: sbrc mp16sL,0 ;if current bit set
  547. sub m16s2,mc16sL ; sub multiplicand Low from result byte 2
  548. sbrc mp16sL,0 ;if current bit set
  549. sbc m16s3,mc16sH ; sub multiplicand High from result byte 3
  550. asr m16s3 ;shift right result and multiplier
  551. ror m16s2
  552. ror m16s1
  553. ror m16s0
  554. dec mcnt16s ;decrement counter
  555. brne m16s_1 ;if not done, loop more
  556. ret
  557. ;----------------------------------------------------------
  558. ;***** Multiply Two Signed 16-Bit Numbers (-12345*(-4321))
  559. test_mpy16s:
  560. ldi mc16sL,low(-12345)
  561. ldi mc16sH,high(-12345)
  562. ldi mp16sL,low(-4321)
  563. ldi mp16sH,high(-4321)
  564. rcall mpy16s ;result: m16s3:m16s2:m16s1:m16s0
  565. ;=$032df219 (53,342,745)
  566. tmpy: rjmp tmpy
  567.  
  568. test_mpy16s0:
  569. ldi mc16sL,low(123)
  570. ldi mc16sH,high(123)
  571. ldi mp16sL,low(147)
  572. ldi mp16sH,high(147)
  573. rcall mpy16s ;result: m16s3:m16s2:m16s1:m16s0
  574. tmpy0: rjmp tmpy0
  575. ;-----------------------
  576. test_star:
  577. ldi r16,-$7b
  578. mypush r16
  579. ldi r16,$00
  580. mypush r16 ;that's decimal 123 on stack
  581. ldi r16,$93
  582. mypush r16
  583. ldi r16,$00
  584. mypush r16 ; and thats dec'147
  585. rcall star
  586. tsr: rjmp tsr
  587.  
  588. ;--------------------------
  589. ;***************************************************************************
  590. ;*
  591. ;* "div16s" - 16/16 Bit Signed Division
  592. ;*
  593. ;* This subroutine divides signed the two 16 bit numbers
  594. ;* "dd16sH:dd16sL" (dividend) and "dv16sH:dv16sL" (divisor).
  595. ;* The result is placed in "dres16sH:dres16sL" and the remainder in
  596. ;* "drem16sH:drem16sL".
  597. ;*
  598. ;* Number of words :39
  599. ;* Number of cycles :247/263 (Min/Max)
  600. ;* Low registers used :3 (d16s,drem16sL,drem16sH)
  601. ;* High registers used :7 (dres16sL/dd16sL,dres16sH/dd16sH,dv16sL,dv16sH,
  602. ;* dcnt16sH)
  603. ;*
  604. ;***************************************************************************
  605.  
  606. ;***** Subroutine Register Variables
  607.  
  608. .def d16s =r13 ;sign register
  609. .def drem16sL=r14 ;remainder low byte
  610. .def drem16sH=r15 ;remainder high byte
  611. .def dres16sL=r16 ;result low byte
  612. .def dres16sH=r17 ;result high byte
  613. .def dd16sL =r16 ;dividend low byte
  614. .def dd16sH =r17 ;dividend high byte
  615. .def dv16sL =r18 ;divisor low byte
  616. .def dv16sH =r19 ;divisor high byte
  617. .def dcnt16s =r20 ;loop counter
  618.  
  619. ;***** Code
  620.  
  621. div16s: mov d16s,dd16sH ;move dividend High to sign register
  622. eor d16s,dv16sH ;xor divisor High with sign register
  623. sbrs dd16sH,7 ;if MSB in dividend set
  624. rjmp d16s_1
  625. com dd16sH ; change sign of dividend
  626. com dd16sL
  627. subi dd16sL,low(-1)
  628. sbci dd16sL,high(-1)
  629. d16s_1: sbrs dv16sH,7 ;if MSB in divisor set
  630. rjmp d16s_2
  631. com dv16sH ; change sign of divisor
  632. com dv16sL
  633. subi dv16sL,low(-1)
  634. sbci dv16sL,high(-1)
  635. d16s_2: clr drem16sL ;clear remainder Low byte
  636. sub drem16sH,drem16sH;clear remainder High byte and carry
  637. ldi dcnt16s,17 ;init loop counter
  638.  
  639. d16s_3: rol dd16sL ;shift left dividend
  640. rol dd16sH
  641. dec dcnt16s ;decrement counter
  642. brne d16s_5 ;if done
  643. sbrs d16s,7 ; if MSB in sign register set
  644. rjmp d16s_4
  645. com dres16sH ; change sign of result
  646. com dres16sL
  647. subi dres16sL,low(-1)
  648. sbci dres16sH,high(-1)
  649. d16s_4: ret ; return
  650. d16s_5: rol drem16sL ;shift dividend into remainder
  651. rol drem16sH
  652. sub drem16sL,dv16sL ;remainder = remainder - divisor
  653. sbc drem16sH,dv16sH ;
  654. brcc d16s_6 ;if result negative
  655. add drem16sL,dv16sL ; restore remainder
  656. adc drem16sH,dv16sH
  657. clc ; clear carry to be shifted into result
  658. rjmp d16s_3 ;else
  659. d16s_6: sec ; set carry to be shifted into result
  660. rjmp d16s_3
  661.  
  662. ;-----------------------------------------------
  663.  
  664. test_div16s:
  665. ;***** Divide Two Signed 16-Bit Numbers (-22,222/10)
  666. ldi dd16sL,low(-22222)
  667. ldi dd16sH,high(-22222)
  668. ldi dv16sL,low(10)
  669. ldi dv16sH,high(10)
  670. rcall div16s ;result: $f752 (-2222)
  671. ;remainder: $0002 (2)
  672.  
  673. forever:rjmp forever
  674. ;----------------------------------
  675. test_slashMod:
  676. ldi r16,$12
  677. mypush r16
  678. ldi r16,$34
  679. mypush r16
  680. ldi r16,$56 ;NB this is $3412 not $1234
  681. mypush r16
  682. ldi r16,$00
  683. mypush r16
  684. rcall slashMod ;$3412 / $56 = $9b rem 0 works
  685. tslm: rjmp tslm
Advertisement
Add Comment
Please, Sign In to add comment