lib1funcs.S 69 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315
  1. /* -*- Mode: Asm -*- */
  2. /* Copyright (C) 1998-2022 Free Software Foundation, Inc.
  3. Contributed by Denis Chertykov <chertykov@gmail.com>
  4. This file is free software; you can redistribute it and/or modify it
  5. under the terms of the GNU General Public License as published by the
  6. Free Software Foundation; either version 3, or (at your option) any
  7. later version.
  8. This file is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. Under Section 7 of GPL version 3, you are granted additional
  13. permissions described in the GCC Runtime Library Exception, version
  14. 3.1, as published by the Free Software Foundation.
  15. You should have received a copy of the GNU General Public License and
  16. a copy of the GCC Runtime Library Exception along with this program;
  17. see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  18. <http://www.gnu.org/licenses/>. */
  19. #if defined (__AVR_TINY__)
  20. #define __zero_reg__ r17
  21. #define __tmp_reg__ r16
  22. #else
  23. #define __zero_reg__ r1
  24. #define __tmp_reg__ r0
  25. #endif
  26. #define __SREG__ 0x3f
  27. #if defined (__AVR_HAVE_SPH__)
  28. #define __SP_H__ 0x3e
  29. #endif
  30. #define __SP_L__ 0x3d
  31. #define __RAMPZ__ 0x3B
  32. #define __EIND__ 0x3C
  33. /* Most of the functions here are called directly from avr.md
  34. patterns, instead of using the standard libcall mechanisms.
  35. This can make better code because GCC knows exactly which
  36. of the call-used registers (not all of them) are clobbered. */
  37. /* FIXME: At present, there is no SORT directive in the linker
  38. script so that we must not assume that different modules
  39. in the same input section like .libgcc.text.mul will be
  40. located close together. Therefore, we cannot use
  41. RCALL/RJMP to call a function like __udivmodhi4 from
  42. __divmodhi4 and have to use lengthy XCALL/XJMP even
  43. though they are in the same input section and all same
  44. input sections together are small enough to reach every
  45. location with a RCALL/RJMP instruction. */
  46. #if defined (__AVR_HAVE_EIJMP_EICALL__) && !defined (__AVR_HAVE_ELPMX__)
  47. #error device not supported
  48. #endif
  49. .macro mov_l r_dest, r_src
  50. #if defined (__AVR_HAVE_MOVW__)
  51. movw \r_dest, \r_src
  52. #else
  53. mov \r_dest, \r_src
  54. #endif
  55. .endm
  56. .macro mov_h r_dest, r_src
  57. #if defined (__AVR_HAVE_MOVW__)
  58. ; empty
  59. #else
  60. mov \r_dest, \r_src
  61. #endif
  62. .endm
  63. .macro wmov r_dest, r_src
  64. #if defined (__AVR_HAVE_MOVW__)
  65. movw \r_dest, \r_src
  66. #else
  67. mov \r_dest, \r_src
  68. mov \r_dest+1, \r_src+1
  69. #endif
  70. .endm
  71. #if defined (__AVR_HAVE_JMP_CALL__)
  72. #define XCALL call
  73. #define XJMP jmp
  74. #else
  75. #define XCALL rcall
  76. #define XJMP rjmp
  77. #endif
  78. #if defined (__AVR_HAVE_EIJMP_EICALL__)
  79. #define XICALL eicall
  80. #define XIJMP eijmp
  81. #else
  82. #define XICALL icall
  83. #define XIJMP ijmp
  84. #endif
  85. ;; Prologue stuff
  86. .macro do_prologue_saves n_pushed n_frame=0
  87. ldi r26, lo8(\n_frame)
  88. ldi r27, hi8(\n_frame)
  89. ldi r30, lo8(gs(.L_prologue_saves.\@))
  90. ldi r31, hi8(gs(.L_prologue_saves.\@))
  91. XJMP __prologue_saves__ + ((18 - (\n_pushed)) * 2)
  92. .L_prologue_saves.\@:
  93. .endm
  94. ;; Epilogue stuff
  95. .macro do_epilogue_restores n_pushed n_frame=0
  96. in r28, __SP_L__
  97. #ifdef __AVR_HAVE_SPH__
  98. in r29, __SP_H__
  99. .if \n_frame > 63
  100. subi r28, lo8(-\n_frame)
  101. sbci r29, hi8(-\n_frame)
  102. .elseif \n_frame > 0
  103. adiw r28, \n_frame
  104. .endif
  105. #else
  106. clr r29
  107. .if \n_frame > 0
  108. subi r28, lo8(-\n_frame)
  109. .endif
  110. #endif /* HAVE SPH */
  111. ldi r30, \n_pushed
  112. XJMP __epilogue_restores__ + ((18 - (\n_pushed)) * 2)
  113. .endm
  114. ;; Support function entry and exit for convenience
  115. .macro wsubi r_arg1, i_arg2
  116. #if defined (__AVR_TINY__)
  117. subi \r_arg1, lo8(\i_arg2)
  118. sbci \r_arg1+1, hi8(\i_arg2)
  119. #else
  120. sbiw \r_arg1, \i_arg2
  121. #endif
  122. .endm
  123. .macro waddi r_arg1, i_arg2
  124. #if defined (__AVR_TINY__)
  125. subi \r_arg1, lo8(-\i_arg2)
  126. sbci \r_arg1+1, hi8(-\i_arg2)
  127. #else
  128. adiw \r_arg1, \i_arg2
  129. #endif
  130. .endm
  131. .macro DEFUN name
  132. .global \name
  133. .func \name
  134. \name:
  135. .endm
  136. .macro ENDF name
  137. .size \name, .-\name
  138. .endfunc
  139. .endm
  140. .macro FALIAS name
  141. .global \name
  142. .func \name
  143. \name:
  144. .size \name, .-\name
  145. .endfunc
  146. .endm
  147. ;; Skip next instruction, typically a jump target
  148. #define skip cpse 16,16
  149. ;; Negate a 2-byte value held in consecutive registers
  150. .macro NEG2 reg
  151. com \reg+1
  152. neg \reg
  153. sbci \reg+1, -1
  154. .endm
  155. ;; Negate a 4-byte value held in consecutive registers
  156. ;; Sets the V flag for signed overflow tests if REG >= 16
  157. .macro NEG4 reg
  158. com \reg+3
  159. com \reg+2
  160. com \reg+1
  161. .if \reg >= 16
  162. neg \reg
  163. sbci \reg+1, -1
  164. sbci \reg+2, -1
  165. sbci \reg+3, -1
  166. .else
  167. com \reg
  168. adc \reg, __zero_reg__
  169. adc \reg+1, __zero_reg__
  170. adc \reg+2, __zero_reg__
  171. adc \reg+3, __zero_reg__
  172. .endif
  173. .endm
  174. #define exp_lo(N) hlo8 ((N) << 23)
  175. #define exp_hi(N) hhi8 ((N) << 23)
  176. .section .text.libgcc.mul, "ax", @progbits
  177. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  178. /* Note: mulqi3, mulhi3 are open-coded on the enhanced core. */
  179. #if !defined (__AVR_HAVE_MUL__)
  180. /*******************************************************
  181. Multiplication 8 x 8 without MUL
  182. *******************************************************/
  183. #if defined (L_mulqi3)
  184. #define r_arg2 r22 /* multiplicand */
  185. #define r_arg1 r24 /* multiplier */
  186. #define r_res __tmp_reg__ /* result */
  187. DEFUN __mulqi3
  188. clr r_res ; clear result
  189. __mulqi3_loop:
  190. sbrc r_arg1,0
  191. add r_res,r_arg2
  192. add r_arg2,r_arg2 ; shift multiplicand
  193. breq __mulqi3_exit ; while multiplicand != 0
  194. lsr r_arg1 ;
  195. brne __mulqi3_loop ; exit if multiplier = 0
  196. __mulqi3_exit:
  197. mov r_arg1,r_res ; result to return register
  198. ret
  199. ENDF __mulqi3
  200. #undef r_arg2
  201. #undef r_arg1
  202. #undef r_res
  203. #endif /* defined (L_mulqi3) */
  204. /*******************************************************
  205. Widening Multiplication 16 = 8 x 8 without MUL
  206. Multiplication 16 x 16 without MUL
  207. *******************************************************/
  208. #define A0 22
  209. #define A1 23
  210. #define B0 24
  211. #define BB0 20
  212. #define B1 25
  213. ;; Output overlaps input, thus expand result in CC0/1
  214. #define C0 24
  215. #define C1 25
  216. #define CC0 __tmp_reg__
  217. #define CC1 21
  218. #if defined (L_umulqihi3)
  219. ;;; R25:R24 = (unsigned int) R22 * (unsigned int) R24
  220. ;;; (C1:C0) = (unsigned int) A0 * (unsigned int) B0
  221. ;;; Clobbers: __tmp_reg__, R21..R23
  222. DEFUN __umulqihi3
  223. clr A1
  224. clr B1
  225. XJMP __mulhi3
  226. ENDF __umulqihi3
  227. #endif /* L_umulqihi3 */
  228. #if defined (L_mulqihi3)
  229. ;;; R25:R24 = (signed int) R22 * (signed int) R24
  230. ;;; (C1:C0) = (signed int) A0 * (signed int) B0
  231. ;;; Clobbers: __tmp_reg__, R20..R23
  232. DEFUN __mulqihi3
  233. ;; Sign-extend B0
  234. clr B1
  235. sbrc B0, 7
  236. com B1
  237. ;; The multiplication runs twice as fast if A1 is zero, thus:
  238. ;; Zero-extend A0
  239. clr A1
  240. #ifdef __AVR_HAVE_JMP_CALL__
  241. ;; Store B0 * sign of A
  242. clr BB0
  243. sbrc A0, 7
  244. mov BB0, B0
  245. call __mulhi3
  246. #else /* have no CALL */
  247. ;; Skip sign-extension of A if A >= 0
  248. ;; Same size as with the first alternative but avoids errata skip
  249. ;; and is faster if A >= 0
  250. sbrs A0, 7
  251. rjmp __mulhi3
  252. ;; If A < 0 store B
  253. mov BB0, B0
  254. rcall __mulhi3
  255. #endif /* HAVE_JMP_CALL */
  256. ;; 1-extend A after the multiplication
  257. sub C1, BB0
  258. ret
  259. ENDF __mulqihi3
  260. #endif /* L_mulqihi3 */
  261. #if defined (L_mulhi3)
  262. ;;; R25:R24 = R23:R22 * R25:R24
  263. ;;; (C1:C0) = (A1:A0) * (B1:B0)
  264. ;;; Clobbers: __tmp_reg__, R21..R23
  265. DEFUN __mulhi3
  266. ;; Clear result
  267. clr CC0
  268. clr CC1
  269. rjmp 3f
  270. 1:
  271. ;; Bit n of A is 1 --> C += B << n
  272. add CC0, B0
  273. adc CC1, B1
  274. 2:
  275. lsl B0
  276. rol B1
  277. 3:
  278. ;; If B == 0 we are ready
  279. wsubi B0, 0
  280. breq 9f
  281. ;; Carry = n-th bit of A
  282. lsr A1
  283. ror A0
  284. ;; If bit n of A is set, then go add B * 2^n to C
  285. brcs 1b
  286. ;; Carry = 0 --> The ROR above acts like CP A0, 0
  287. ;; Thus, it is sufficient to CPC the high part to test A against 0
  288. cpc A1, __zero_reg__
  289. ;; Only proceed if A != 0
  290. brne 2b
  291. 9:
  292. ;; Move Result into place
  293. mov C0, CC0
  294. mov C1, CC1
  295. ret
  296. ENDF __mulhi3
  297. #endif /* L_mulhi3 */
  298. #undef A0
  299. #undef A1
  300. #undef B0
  301. #undef BB0
  302. #undef B1
  303. #undef C0
  304. #undef C1
  305. #undef CC0
  306. #undef CC1
  307. #define A0 22
  308. #define A1 A0+1
  309. #define A2 A0+2
  310. #define A3 A0+3
  311. #define B0 18
  312. #define B1 B0+1
  313. #define B2 B0+2
  314. #define B3 B0+3
  315. #define CC0 26
  316. #define CC1 CC0+1
  317. #define CC2 30
  318. #define CC3 CC2+1
  319. #define C0 22
  320. #define C1 C0+1
  321. #define C2 C0+2
  322. #define C3 C0+3
  323. /*******************************************************
  324. Widening Multiplication 32 = 16 x 16 without MUL
  325. *******************************************************/
  326. #if defined (L_umulhisi3)
  327. DEFUN __umulhisi3
  328. wmov B0, 24
  329. ;; Zero-extend B
  330. clr B2
  331. clr B3
  332. ;; Zero-extend A
  333. wmov A2, B2
  334. XJMP __mulsi3
  335. ENDF __umulhisi3
  336. #endif /* L_umulhisi3 */
  337. #if defined (L_mulhisi3)
  338. DEFUN __mulhisi3
  339. wmov B0, 24
  340. ;; Sign-extend B
  341. lsl r25
  342. sbc B2, B2
  343. mov B3, B2
  344. #ifdef __AVR_ERRATA_SKIP_JMP_CALL__
  345. ;; Sign-extend A
  346. clr A2
  347. sbrc A1, 7
  348. com A2
  349. mov A3, A2
  350. XJMP __mulsi3
  351. #else /* no __AVR_ERRATA_SKIP_JMP_CALL__ */
  352. ;; Zero-extend A and __mulsi3 will run at least twice as fast
  353. ;; compared to a sign-extended A.
  354. clr A2
  355. clr A3
  356. sbrs A1, 7
  357. XJMP __mulsi3
  358. ;; If A < 0 then perform the B * 0xffff.... before the
  359. ;; very multiplication by initializing the high part of the
  360. ;; result CC with -B.
  361. wmov CC2, A2
  362. sub CC2, B0
  363. sbc CC3, B1
  364. XJMP __mulsi3_helper
  365. #endif /* __AVR_ERRATA_SKIP_JMP_CALL__ */
  366. ENDF __mulhisi3
  367. #endif /* L_mulhisi3 */
  368. /*******************************************************
  369. Multiplication 32 x 32 without MUL
  370. *******************************************************/
  371. #if defined (L_mulsi3)
  372. DEFUN __mulsi3
  373. #if defined (__AVR_TINY__)
  374. in r26, __SP_L__ ; safe to use X, as it is CC0/CC1
  375. in r27, __SP_H__
  376. subi r26, lo8(-3) ; Add 3 to point past return address
  377. sbci r27, hi8(-3)
  378. push B0 ; save callee saved regs
  379. push B1
  380. ld B0, X+ ; load from caller stack
  381. ld B1, X+
  382. ld B2, X+
  383. ld B3, X
  384. #endif
  385. ;; Clear result
  386. clr CC2
  387. clr CC3
  388. ;; FALLTHRU
  389. ENDF __mulsi3
  390. DEFUN __mulsi3_helper
  391. clr CC0
  392. clr CC1
  393. rjmp 3f
  394. 1: ;; If bit n of A is set, then add B * 2^n to the result in CC
  395. ;; CC += B
  396. add CC0,B0 $ adc CC1,B1 $ adc CC2,B2 $ adc CC3,B3
  397. 2: ;; B <<= 1
  398. lsl B0 $ rol B1 $ rol B2 $ rol B3
  399. 3: ;; A >>= 1: Carry = n-th bit of A
  400. lsr A3 $ ror A2 $ ror A1 $ ror A0
  401. brcs 1b
  402. ;; Only continue if A != 0
  403. sbci A1, 0
  404. brne 2b
  405. wsubi A2, 0
  406. brne 2b
  407. ;; All bits of A are consumed: Copy result to return register C
  408. wmov C0, CC0
  409. wmov C2, CC2
  410. #if defined (__AVR_TINY__)
  411. pop B1 ; restore callee saved regs
  412. pop B0
  413. #endif /* defined (__AVR_TINY__) */
  414. ret
  415. ENDF __mulsi3_helper
  416. #endif /* L_mulsi3 */
  417. #undef A0
  418. #undef A1
  419. #undef A2
  420. #undef A3
  421. #undef B0
  422. #undef B1
  423. #undef B2
  424. #undef B3
  425. #undef C0
  426. #undef C1
  427. #undef C2
  428. #undef C3
  429. #undef CC0
  430. #undef CC1
  431. #undef CC2
  432. #undef CC3
  433. #endif /* !defined (__AVR_HAVE_MUL__) */
  434. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  435. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  436. #if defined (__AVR_HAVE_MUL__)
  437. #define A0 26
  438. #define B0 18
  439. #define C0 22
  440. #define A1 A0+1
  441. #define B1 B0+1
  442. #define B2 B0+2
  443. #define B3 B0+3
  444. #define C1 C0+1
  445. #define C2 C0+2
  446. #define C3 C0+3
  447. /*******************************************************
  448. Widening Multiplication 32 = 16 x 16 with MUL
  449. *******************************************************/
  450. #if defined (L_mulhisi3)
  451. ;;; R25:R22 = (signed long) R27:R26 * (signed long) R19:R18
  452. ;;; C3:C0 = (signed long) A1:A0 * (signed long) B1:B0
  453. ;;; Clobbers: __tmp_reg__
  454. DEFUN __mulhisi3
  455. XCALL __umulhisi3
  456. ;; Sign-extend B
  457. tst B1
  458. brpl 1f
  459. sub C2, A0
  460. sbc C3, A1
  461. 1: ;; Sign-extend A
  462. XJMP __usmulhisi3_tail
  463. ENDF __mulhisi3
  464. #endif /* L_mulhisi3 */
  465. #if defined (L_usmulhisi3)
  466. ;;; R25:R22 = (signed long) R27:R26 * (unsigned long) R19:R18
  467. ;;; C3:C0 = (signed long) A1:A0 * (unsigned long) B1:B0
  468. ;;; Clobbers: __tmp_reg__
  469. DEFUN __usmulhisi3
  470. XCALL __umulhisi3
  471. ;; FALLTHRU
  472. ENDF __usmulhisi3
  473. DEFUN __usmulhisi3_tail
  474. ;; Sign-extend A
  475. sbrs A1, 7
  476. ret
  477. sub C2, B0
  478. sbc C3, B1
  479. ret
  480. ENDF __usmulhisi3_tail
  481. #endif /* L_usmulhisi3 */
  482. #if defined (L_umulhisi3)
  483. ;;; R25:R22 = (unsigned long) R27:R26 * (unsigned long) R19:R18
  484. ;;; C3:C0 = (unsigned long) A1:A0 * (unsigned long) B1:B0
  485. ;;; Clobbers: __tmp_reg__
  486. DEFUN __umulhisi3
  487. mul A0, B0
  488. movw C0, r0
  489. mul A1, B1
  490. movw C2, r0
  491. mul A0, B1
  492. #ifdef __AVR_HAVE_JMP_CALL__
  493. ;; This function is used by many other routines, often multiple times.
  494. ;; Therefore, if the flash size is not too limited, avoid the RCALL
  495. ;; and inverst 6 Bytes to speed things up.
  496. add C1, r0
  497. adc C2, r1
  498. clr __zero_reg__
  499. adc C3, __zero_reg__
  500. #else
  501. rcall 1f
  502. #endif
  503. mul A1, B0
  504. 1: add C1, r0
  505. adc C2, r1
  506. clr __zero_reg__
  507. adc C3, __zero_reg__
  508. ret
  509. ENDF __umulhisi3
  510. #endif /* L_umulhisi3 */
  511. /*******************************************************
  512. Widening Multiplication 32 = 16 x 32 with MUL
  513. *******************************************************/
  514. #if defined (L_mulshisi3)
  515. ;;; R25:R22 = (signed long) R27:R26 * R21:R18
  516. ;;; (C3:C0) = (signed long) A1:A0 * B3:B0
  517. ;;; Clobbers: __tmp_reg__
  518. DEFUN __mulshisi3
  519. #ifdef __AVR_ERRATA_SKIP_JMP_CALL__
  520. ;; Some cores have problem skipping 2-word instruction
  521. tst A1
  522. brmi __mulohisi3
  523. #else
  524. sbrs A1, 7
  525. #endif /* __AVR_HAVE_JMP_CALL__ */
  526. XJMP __muluhisi3
  527. ;; FALLTHRU
  528. ENDF __mulshisi3
  529. ;;; R25:R22 = (one-extended long) R27:R26 * R21:R18
  530. ;;; (C3:C0) = (one-extended long) A1:A0 * B3:B0
  531. ;;; Clobbers: __tmp_reg__
  532. DEFUN __mulohisi3
  533. XCALL __muluhisi3
  534. ;; One-extend R27:R26 (A1:A0)
  535. sub C2, B0
  536. sbc C3, B1
  537. ret
  538. ENDF __mulohisi3
  539. #endif /* L_mulshisi3 */
  540. #if defined (L_muluhisi3)
  541. ;;; R25:R22 = (unsigned long) R27:R26 * R21:R18
  542. ;;; (C3:C0) = (unsigned long) A1:A0 * B3:B0
  543. ;;; Clobbers: __tmp_reg__
  544. DEFUN __muluhisi3
  545. XCALL __umulhisi3
  546. mul A0, B3
  547. add C3, r0
  548. mul A1, B2
  549. add C3, r0
  550. mul A0, B2
  551. add C2, r0
  552. adc C3, r1
  553. clr __zero_reg__
  554. ret
  555. ENDF __muluhisi3
  556. #endif /* L_muluhisi3 */
  557. /*******************************************************
  558. Multiplication 32 x 32 with MUL
  559. *******************************************************/
  560. #if defined (L_mulsi3)
  561. ;;; R25:R22 = R25:R22 * R21:R18
  562. ;;; (C3:C0) = C3:C0 * B3:B0
  563. ;;; Clobbers: R26, R27, __tmp_reg__
  564. DEFUN __mulsi3
  565. movw A0, C0
  566. push C2
  567. push C3
  568. XCALL __muluhisi3
  569. pop A1
  570. pop A0
  571. ;; A1:A0 now contains the high word of A
  572. mul A0, B0
  573. add C2, r0
  574. adc C3, r1
  575. mul A0, B1
  576. add C3, r0
  577. mul A1, B0
  578. add C3, r0
  579. clr __zero_reg__
  580. ret
  581. ENDF __mulsi3
  582. #endif /* L_mulsi3 */
  583. #undef A0
  584. #undef A1
  585. #undef B0
  586. #undef B1
  587. #undef B2
  588. #undef B3
  589. #undef C0
  590. #undef C1
  591. #undef C2
  592. #undef C3
  593. #endif /* __AVR_HAVE_MUL__ */
  594. /*******************************************************
  595. Multiplication 24 x 24 with MUL
  596. *******************************************************/
  597. #if defined (L_mulpsi3)
  598. ;; A[0..2]: In: Multiplicand; Out: Product
  599. #define A0 22
  600. #define A1 A0+1
  601. #define A2 A0+2
  602. ;; B[0..2]: In: Multiplier
  603. #define B0 18
  604. #define B1 B0+1
  605. #define B2 B0+2
  606. #if defined (__AVR_HAVE_MUL__)
  607. ;; C[0..2]: Expand Result
  608. #define C0 22
  609. #define C1 C0+1
  610. #define C2 C0+2
  611. ;; R24:R22 *= R20:R18
  612. ;; Clobbers: r21, r25, r26, r27, __tmp_reg__
  613. #define AA0 26
  614. #define AA2 21
  615. DEFUN __mulpsi3
  616. wmov AA0, A0
  617. mov AA2, A2
  618. XCALL __umulhisi3
  619. mul AA2, B0 $ add C2, r0
  620. mul AA0, B2 $ add C2, r0
  621. clr __zero_reg__
  622. ret
  623. ENDF __mulpsi3
  624. #undef AA2
  625. #undef AA0
  626. #undef C2
  627. #undef C1
  628. #undef C0
  629. #else /* !HAVE_MUL */
  630. ;; C[0..2]: Expand Result
  631. #if defined (__AVR_TINY__)
  632. #define C0 16
  633. #else
  634. #define C0 0
  635. #endif /* defined (__AVR_TINY__) */
  636. #define C1 C0+1
  637. #define C2 21
  638. ;; R24:R22 *= R20:R18
  639. ;; Clobbers: __tmp_reg__, R18, R19, R20, R21
  640. DEFUN __mulpsi3
  641. #if defined (__AVR_TINY__)
  642. in r26,__SP_L__
  643. in r27,__SP_H__
  644. subi r26, lo8(-3) ; Add 3 to point past return address
  645. sbci r27, hi8(-3)
  646. push B0 ; save callee saved regs
  647. push B1
  648. ld B0,X+ ; load from caller stack
  649. ld B1,X+
  650. ld B2,X+
  651. #endif /* defined (__AVR_TINY__) */
  652. ;; C[] = 0
  653. clr __tmp_reg__
  654. clr C2
  655. 0: ;; Shift N-th Bit of B[] into Carry. N = 24 - Loop
  656. LSR B2 $ ror B1 $ ror B0
  657. ;; If the N-th Bit of B[] was set...
  658. brcc 1f
  659. ;; ...then add A[] * 2^N to the Result C[]
  660. ADD C0,A0 $ adc C1,A1 $ adc C2,A2
  661. 1: ;; Multiply A[] by 2
  662. LSL A0 $ rol A1 $ rol A2
  663. ;; Loop until B[] is 0
  664. subi B0,0 $ sbci B1,0 $ sbci B2,0
  665. brne 0b
  666. ;; Copy C[] to the return Register A[]
  667. wmov A0, C0
  668. mov A2, C2
  669. clr __zero_reg__
  670. #if defined (__AVR_TINY__)
  671. pop B1
  672. pop B0
  673. #endif /* (__AVR_TINY__) */
  674. ret
  675. ENDF __mulpsi3
  676. #undef C2
  677. #undef C1
  678. #undef C0
  679. #endif /* HAVE_MUL */
  680. #undef B2
  681. #undef B1
  682. #undef B0
  683. #undef A2
  684. #undef A1
  685. #undef A0
  686. #endif /* L_mulpsi3 */
  687. #if defined (L_mulsqipsi3) && defined (__AVR_HAVE_MUL__)
  688. ;; A[0..2]: In: Multiplicand
  689. #define A0 22
  690. #define A1 A0+1
  691. #define A2 A0+2
  692. ;; BB: In: Multiplier
  693. #define BB 25
  694. ;; C[0..2]: Result
  695. #define C0 18
  696. #define C1 C0+1
  697. #define C2 C0+2
  698. ;; C[] = A[] * sign_extend (BB)
  699. DEFUN __mulsqipsi3
  700. mul A0, BB
  701. movw C0, r0
  702. mul A2, BB
  703. mov C2, r0
  704. mul A1, BB
  705. add C1, r0
  706. adc C2, r1
  707. clr __zero_reg__
  708. sbrs BB, 7
  709. ret
  710. ;; One-extend BB
  711. sub C1, A0
  712. sbc C2, A1
  713. ret
  714. ENDF __mulsqipsi3
  715. #undef C2
  716. #undef C1
  717. #undef C0
  718. #undef BB
  719. #undef A2
  720. #undef A1
  721. #undef A0
  722. #endif /* L_mulsqipsi3 && HAVE_MUL */
  723. /*******************************************************
  724. Multiplication 64 x 64
  725. *******************************************************/
  726. ;; A[] = A[] * B[]
  727. ;; A[0..7]: In: Multiplicand
  728. ;; Out: Product
  729. #define A0 18
  730. #define A1 A0+1
  731. #define A2 A0+2
  732. #define A3 A0+3
  733. #define A4 A0+4
  734. #define A5 A0+5
  735. #define A6 A0+6
  736. #define A7 A0+7
  737. ;; B[0..7]: In: Multiplier
  738. #define B0 10
  739. #define B1 B0+1
  740. #define B2 B0+2
  741. #define B3 B0+3
  742. #define B4 B0+4
  743. #define B5 B0+5
  744. #define B6 B0+6
  745. #define B7 B0+7
  746. #ifndef __AVR_TINY__
  747. #if defined (__AVR_HAVE_MUL__)
  748. ;; Define C[] for convenience
  749. ;; Notice that parts of C[] overlap A[] respective B[]
  750. #define C0 16
  751. #define C1 C0+1
  752. #define C2 20
  753. #define C3 C2+1
  754. #define C4 28
  755. #define C5 C4+1
  756. #define C6 C4+2
  757. #define C7 C4+3
  758. #if defined (L_muldi3)
  759. ;; A[] *= B[]
  760. ;; R25:R18 *= R17:R10
  761. ;; Ordinary ABI-Function
  762. DEFUN __muldi3
  763. push r29
  764. push r28
  765. push r17
  766. push r16
  767. ;; Counting in Words, we have to perform a 4 * 4 Multiplication
  768. ;; 3 * 0 + 0 * 3
  769. mul A7,B0 $ $ mov C7,r0
  770. mul A0,B7 $ $ add C7,r0
  771. mul A6,B1 $ $ add C7,r0
  772. mul A6,B0 $ mov C6,r0 $ add C7,r1
  773. mul B6,A1 $ $ add C7,r0
  774. mul B6,A0 $ add C6,r0 $ adc C7,r1
  775. ;; 1 * 2
  776. mul A2,B4 $ add C6,r0 $ adc C7,r1
  777. mul A3,B4 $ $ add C7,r0
  778. mul A2,B5 $ $ add C7,r0
  779. push A5
  780. push A4
  781. push B1
  782. push B0
  783. push A3
  784. push A2
  785. ;; 0 * 0
  786. wmov 26, B0
  787. XCALL __umulhisi3
  788. wmov C0, 22
  789. wmov C2, 24
  790. ;; 0 * 2
  791. wmov 26, B4
  792. XCALL __umulhisi3 $ wmov C4,22 $ add C6,24 $ adc C7,25
  793. wmov 26, B2
  794. ;; 0 * 1
  795. XCALL __muldi3_6
  796. pop A0
  797. pop A1
  798. ;; 1 * 1
  799. wmov 26, B2
  800. XCALL __umulhisi3 $ add C4,22 $ adc C5,23 $ adc C6,24 $ adc C7,25
  801. pop r26
  802. pop r27
  803. ;; 1 * 0
  804. XCALL __muldi3_6
  805. pop A0
  806. pop A1
  807. ;; 2 * 0
  808. XCALL __umulhisi3 $ add C4,22 $ adc C5,23 $ adc C6,24 $ adc C7,25
  809. ;; 2 * 1
  810. wmov 26, B2
  811. XCALL __umulhisi3 $ $ $ add C6,22 $ adc C7,23
  812. ;; A[] = C[]
  813. wmov A0, C0
  814. ;; A2 = C2 already
  815. wmov A4, C4
  816. wmov A6, C6
  817. pop r16
  818. pop r17
  819. pop r28
  820. pop r29
  821. ret
  822. ENDF __muldi3
  823. #endif /* L_muldi3 */
  824. #if defined (L_muldi3_6)
  825. ;; A helper for some 64-bit multiplications with MUL available
  826. DEFUN __muldi3_6
  827. __muldi3_6:
  828. XCALL __umulhisi3
  829. add C2, 22
  830. adc C3, 23
  831. adc C4, 24
  832. adc C5, 25
  833. brcc 0f
  834. adiw C6, 1
  835. 0: ret
  836. ENDF __muldi3_6
  837. #endif /* L_muldi3_6 */
  838. #undef C7
  839. #undef C6
  840. #undef C5
  841. #undef C4
  842. #undef C3
  843. #undef C2
  844. #undef C1
  845. #undef C0
  846. #else /* !HAVE_MUL */
  847. #if defined (L_muldi3)
  848. #define C0 26
  849. #define C1 C0+1
  850. #define C2 C0+2
  851. #define C3 C0+3
  852. #define C4 C0+4
  853. #define C5 C0+5
  854. #define C6 0
  855. #define C7 C6+1
  856. #define Loop 9
  857. ;; A[] *= B[]
  858. ;; R25:R18 *= R17:R10
  859. ;; Ordinary ABI-Function
  860. DEFUN __muldi3
  861. push r29
  862. push r28
  863. push Loop
  864. ldi C0, 64
  865. mov Loop, C0
  866. ;; C[] = 0
  867. clr __tmp_reg__
  868. wmov C0, 0
  869. wmov C2, 0
  870. wmov C4, 0
  871. 0: ;; Rotate B[] right by 1 and set Carry to the N-th Bit of B[]
  872. ;; where N = 64 - Loop.
  873. ;; Notice that B[] = B[] >>> 64 so after this Routine has finished,
  874. ;; B[] will have its initial Value again.
  875. LSR B7 $ ror B6 $ ror B5 $ ror B4
  876. ror B3 $ ror B2 $ ror B1 $ ror B0
  877. ;; If the N-th Bit of B[] was set then...
  878. brcc 1f
  879. ;; ...finish Rotation...
  880. ori B7, 1 << 7
  881. ;; ...and add A[] * 2^N to the Result C[]
  882. ADD C0,A0 $ adc C1,A1 $ adc C2,A2 $ adc C3,A3
  883. adc C4,A4 $ adc C5,A5 $ adc C6,A6 $ adc C7,A7
  884. 1: ;; Multiply A[] by 2
  885. LSL A0 $ rol A1 $ rol A2 $ rol A3
  886. rol A4 $ rol A5 $ rol A6 $ rol A7
  887. dec Loop
  888. brne 0b
  889. ;; We expanded the Result in C[]
  890. ;; Copy Result to the Return Register A[]
  891. wmov A0, C0
  892. wmov A2, C2
  893. wmov A4, C4
  894. wmov A6, C6
  895. clr __zero_reg__
  896. pop Loop
  897. pop r28
  898. pop r29
  899. ret
  900. ENDF __muldi3
  901. #undef Loop
  902. #undef C7
  903. #undef C6
  904. #undef C5
  905. #undef C4
  906. #undef C3
  907. #undef C2
  908. #undef C1
  909. #undef C0
  910. #endif /* L_muldi3 */
  911. #endif /* HAVE_MUL */
  912. #endif /* if not __AVR_TINY__ */
  913. #undef B7
  914. #undef B6
  915. #undef B5
  916. #undef B4
  917. #undef B3
  918. #undef B2
  919. #undef B1
  920. #undef B0
  921. #undef A7
  922. #undef A6
  923. #undef A5
  924. #undef A4
  925. #undef A3
  926. #undef A2
  927. #undef A1
  928. #undef A0
  929. /*******************************************************
  930. Widening Multiplication 64 = 32 x 32 with MUL
  931. *******************************************************/
  932. #if defined (__AVR_HAVE_MUL__)
  933. #define A0 r22
  934. #define A1 r23
  935. #define A2 r24
  936. #define A3 r25
  937. #define B0 r18
  938. #define B1 r19
  939. #define B2 r20
  940. #define B3 r21
  941. #define C0 18
  942. #define C1 C0+1
  943. #define C2 20
  944. #define C3 C2+1
  945. #define C4 28
  946. #define C5 C4+1
  947. #define C6 C4+2
  948. #define C7 C4+3
  949. #if defined (L_umulsidi3)
  950. ;; Unsigned widening 64 = 32 * 32 Multiplication with MUL
  951. ;; R18[8] = R22[4] * R18[4]
  952. ;;
  953. ;; Ordinary ABI Function, but additionally sets
  954. ;; X = R20[2] = B2[2]
  955. ;; Z = R22[2] = A0[2]
  956. DEFUN __umulsidi3
  957. clt
  958. ;; FALLTHRU
  959. ENDF __umulsidi3
  960. ;; T = sign (A)
  961. DEFUN __umulsidi3_helper
  962. push 29 $ push 28 ; Y
  963. wmov 30, A2
  964. ;; Counting in Words, we have to perform 4 Multiplications
  965. ;; 0 * 0
  966. wmov 26, A0
  967. XCALL __umulhisi3
  968. push 23 $ push 22 ; C0
  969. wmov 28, B0
  970. wmov 18, B2
  971. wmov C2, 24
  972. push 27 $ push 26 ; A0
  973. push 19 $ push 18 ; B2
  974. ;;
  975. ;; 18 20 22 24 26 28 30 | B2, B3, A0, A1, C0, C1, Y
  976. ;; B2 C2 -- -- -- B0 A2
  977. ;; 1 * 1
  978. wmov 26, 30 ; A2
  979. XCALL __umulhisi3
  980. ;; Sign-extend A. T holds the sign of A
  981. brtc 0f
  982. ;; Subtract B from the high part of the result
  983. sub 22, 28
  984. sbc 23, 29
  985. sbc 24, 18
  986. sbc 25, 19
  987. 0: wmov 18, 28 ;; B0
  988. wmov C4, 22
  989. wmov C6, 24
  990. ;;
  991. ;; 18 20 22 24 26 28 30 | B2, B3, A0, A1, C0, C1, Y
  992. ;; B0 C2 -- -- A2 C4 C6
  993. ;;
  994. ;; 1 * 0
  995. XCALL __muldi3_6
  996. ;; 0 * 1
  997. pop 26 $ pop 27 ;; B2
  998. pop 18 $ pop 19 ;; A0
  999. XCALL __muldi3_6
  1000. ;; Move result C into place and save A0 in Z
  1001. wmov 22, C4
  1002. wmov 24, C6
  1003. wmov 30, 18 ; A0
  1004. pop C0 $ pop C1
  1005. ;; Epilogue
  1006. pop 28 $ pop 29 ;; Y
  1007. ret
  1008. ENDF __umulsidi3_helper
  1009. #endif /* L_umulsidi3 */
  1010. #if defined (L_mulsidi3)
  1011. ;; Signed widening 64 = 32 * 32 Multiplication
  1012. ;;
  1013. ;; R18[8] = R22[4] * R18[4]
  1014. ;; Ordinary ABI Function
  1015. DEFUN __mulsidi3
  1016. bst A3, 7
  1017. sbrs B3, 7 ; Enhanced core has no skip bug
  1018. XJMP __umulsidi3_helper
  1019. ;; B needs sign-extension
  1020. push A3
  1021. push A2
  1022. XCALL __umulsidi3_helper
  1023. ;; A0 survived in Z
  1024. sub r22, r30
  1025. sbc r23, r31
  1026. pop r26
  1027. pop r27
  1028. sbc r24, r26
  1029. sbc r25, r27
  1030. ret
  1031. ENDF __mulsidi3
  1032. #endif /* L_mulsidi3 */
  1033. #undef A0
  1034. #undef A1
  1035. #undef A2
  1036. #undef A3
  1037. #undef B0
  1038. #undef B1
  1039. #undef B2
  1040. #undef B3
  1041. #undef C0
  1042. #undef C1
  1043. #undef C2
  1044. #undef C3
  1045. #undef C4
  1046. #undef C5
  1047. #undef C6
  1048. #undef C7
  1049. #endif /* HAVE_MUL */
  1050. /**********************************************************
  1051. Widening Multiplication 64 = 32 x 32 without MUL
  1052. **********************************************************/
  1053. #ifndef __AVR_TINY__ /* if not __AVR_TINY__ */
  1054. #if defined (L_mulsidi3) && !defined (__AVR_HAVE_MUL__)
  1055. #define A0 18
  1056. #define A1 A0+1
  1057. #define A2 A0+2
  1058. #define A3 A0+3
  1059. #define A4 A0+4
  1060. #define A5 A0+5
  1061. #define A6 A0+6
  1062. #define A7 A0+7
  1063. #define B0 10
  1064. #define B1 B0+1
  1065. #define B2 B0+2
  1066. #define B3 B0+3
  1067. #define B4 B0+4
  1068. #define B5 B0+5
  1069. #define B6 B0+6
  1070. #define B7 B0+7
  1071. #define AA0 22
  1072. #define AA1 AA0+1
  1073. #define AA2 AA0+2
  1074. #define AA3 AA0+3
  1075. #define BB0 18
  1076. #define BB1 BB0+1
  1077. #define BB2 BB0+2
  1078. #define BB3 BB0+3
  1079. #define Mask r30
  1080. ;; Signed / Unsigned widening 64 = 32 * 32 Multiplication without MUL
  1081. ;;
  1082. ;; R18[8] = R22[4] * R18[4]
  1083. ;; Ordinary ABI Function
  1084. DEFUN __mulsidi3
  1085. set
  1086. skip
  1087. ;; FALLTHRU
  1088. ENDF __mulsidi3
  1089. DEFUN __umulsidi3
  1090. clt ; skipped
  1091. ;; Save 10 Registers: R10..R17, R28, R29
  1092. do_prologue_saves 10
  1093. ldi Mask, 0xff
  1094. bld Mask, 7
  1095. ;; Move B into place...
  1096. wmov B0, BB0
  1097. wmov B2, BB2
  1098. ;; ...and extend it
  1099. and BB3, Mask
  1100. lsl BB3
  1101. sbc B4, B4
  1102. mov B5, B4
  1103. wmov B6, B4
  1104. ;; Move A into place...
  1105. wmov A0, AA0
  1106. wmov A2, AA2
  1107. ;; ...and extend it
  1108. and AA3, Mask
  1109. lsl AA3
  1110. sbc A4, A4
  1111. mov A5, A4
  1112. wmov A6, A4
  1113. XCALL __muldi3
  1114. do_epilogue_restores 10
  1115. ENDF __umulsidi3
  1116. #undef A0
  1117. #undef A1
  1118. #undef A2
  1119. #undef A3
  1120. #undef A4
  1121. #undef A5
  1122. #undef A6
  1123. #undef A7
  1124. #undef B0
  1125. #undef B1
  1126. #undef B2
  1127. #undef B3
  1128. #undef B4
  1129. #undef B5
  1130. #undef B6
  1131. #undef B7
  1132. #undef AA0
  1133. #undef AA1
  1134. #undef AA2
  1135. #undef AA3
  1136. #undef BB0
  1137. #undef BB1
  1138. #undef BB2
  1139. #undef BB3
  1140. #undef Mask
  1141. #endif /* L_mulsidi3 && !HAVE_MUL */
  1142. #endif /* if not __AVR_TINY__ */
  1143. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1144. .section .text.libgcc.div, "ax", @progbits
  1145. /*******************************************************
  1146. Division 8 / 8 => (result + remainder)
  1147. *******************************************************/
  1148. #define r_rem r25 /* remainder */
  1149. #define r_arg1 r24 /* dividend, quotient */
  1150. #define r_arg2 r22 /* divisor */
  1151. #define r_cnt r23 /* loop count */
  1152. #if defined (L_udivmodqi4)
  1153. DEFUN __udivmodqi4
  1154. sub r_rem,r_rem ; clear remainder and carry
  1155. ldi r_cnt,9 ; init loop counter
  1156. rjmp __udivmodqi4_ep ; jump to entry point
  1157. __udivmodqi4_loop:
  1158. rol r_rem ; shift dividend into remainder
  1159. cp r_rem,r_arg2 ; compare remainder & divisor
  1160. brcs __udivmodqi4_ep ; remainder <= divisor
  1161. sub r_rem,r_arg2 ; restore remainder
  1162. __udivmodqi4_ep:
  1163. rol r_arg1 ; shift dividend (with CARRY)
  1164. dec r_cnt ; decrement loop counter
  1165. brne __udivmodqi4_loop
  1166. com r_arg1 ; complement result
  1167. ; because C flag was complemented in loop
  1168. ret
  1169. ENDF __udivmodqi4
  1170. #endif /* defined (L_udivmodqi4) */
  1171. #if defined (L_divmodqi4)
  1172. DEFUN __divmodqi4
  1173. bst r_arg1,7 ; store sign of dividend
  1174. mov __tmp_reg__,r_arg1
  1175. eor __tmp_reg__,r_arg2; r0.7 is sign of result
  1176. sbrc r_arg1,7
  1177. neg r_arg1 ; dividend negative : negate
  1178. sbrc r_arg2,7
  1179. neg r_arg2 ; divisor negative : negate
  1180. XCALL __udivmodqi4 ; do the unsigned div/mod
  1181. brtc __divmodqi4_1
  1182. neg r_rem ; correct remainder sign
  1183. __divmodqi4_1:
  1184. sbrc __tmp_reg__,7
  1185. neg r_arg1 ; correct result sign
  1186. __divmodqi4_exit:
  1187. ret
  1188. ENDF __divmodqi4
  1189. #endif /* defined (L_divmodqi4) */
  1190. #undef r_rem
  1191. #undef r_arg1
  1192. #undef r_arg2
  1193. #undef r_cnt
  1194. /*******************************************************
  1195. Division 16 / 16 => (result + remainder)
  1196. *******************************************************/
  1197. #define r_remL r26 /* remainder Low */
  1198. #define r_remH r27 /* remainder High */
  1199. /* return: remainder */
  1200. #define r_arg1L r24 /* dividend Low */
  1201. #define r_arg1H r25 /* dividend High */
  1202. /* return: quotient */
  1203. #define r_arg2L r22 /* divisor Low */
  1204. #define r_arg2H r23 /* divisor High */
  1205. #define r_cnt r21 /* loop count */
  1206. #if defined (L_udivmodhi4)
  1207. DEFUN __udivmodhi4
  1208. sub r_remL,r_remL
  1209. sub r_remH,r_remH ; clear remainder and carry
  1210. ldi r_cnt,17 ; init loop counter
  1211. rjmp __udivmodhi4_ep ; jump to entry point
  1212. __udivmodhi4_loop:
  1213. rol r_remL ; shift dividend into remainder
  1214. rol r_remH
  1215. cp r_remL,r_arg2L ; compare remainder & divisor
  1216. cpc r_remH,r_arg2H
  1217. brcs __udivmodhi4_ep ; remainder < divisor
  1218. sub r_remL,r_arg2L ; restore remainder
  1219. sbc r_remH,r_arg2H
  1220. __udivmodhi4_ep:
  1221. rol r_arg1L ; shift dividend (with CARRY)
  1222. rol r_arg1H
  1223. dec r_cnt ; decrement loop counter
  1224. brne __udivmodhi4_loop
  1225. com r_arg1L
  1226. com r_arg1H
  1227. ; div/mod results to return registers, as for the div() function
  1228. mov_l r_arg2L, r_arg1L ; quotient
  1229. mov_h r_arg2H, r_arg1H
  1230. mov_l r_arg1L, r_remL ; remainder
  1231. mov_h r_arg1H, r_remH
  1232. ret
  1233. ENDF __udivmodhi4
  1234. #endif /* defined (L_udivmodhi4) */
  1235. #if defined (L_divmodhi4)
  1236. DEFUN __divmodhi4
  1237. .global _div
  1238. _div:
  1239. bst r_arg1H,7 ; store sign of dividend
  1240. mov __tmp_reg__,r_arg2H
  1241. brtc 0f
  1242. com __tmp_reg__ ; r0.7 is sign of result
  1243. rcall __divmodhi4_neg1 ; dividend negative: negate
  1244. 0:
  1245. sbrc r_arg2H,7
  1246. rcall __divmodhi4_neg2 ; divisor negative: negate
  1247. XCALL __udivmodhi4 ; do the unsigned div/mod
  1248. sbrc __tmp_reg__,7
  1249. rcall __divmodhi4_neg2 ; correct remainder sign
  1250. brtc __divmodhi4_exit
  1251. __divmodhi4_neg1:
  1252. ;; correct dividend/remainder sign
  1253. com r_arg1H
  1254. neg r_arg1L
  1255. sbci r_arg1H,0xff
  1256. ret
  1257. __divmodhi4_neg2:
  1258. ;; correct divisor/result sign
  1259. com r_arg2H
  1260. neg r_arg2L
  1261. sbci r_arg2H,0xff
  1262. __divmodhi4_exit:
  1263. ret
  1264. ENDF __divmodhi4
  1265. #endif /* defined (L_divmodhi4) */
  1266. #undef r_remH
  1267. #undef r_remL
  1268. #undef r_arg1H
  1269. #undef r_arg1L
  1270. #undef r_arg2H
  1271. #undef r_arg2L
  1272. #undef r_cnt
  1273. /*******************************************************
  1274. Division 24 / 24 => (result + remainder)
  1275. *******************************************************/
  1276. ;; A[0..2]: In: Dividend; Out: Quotient
  1277. #define A0 22
  1278. #define A1 A0+1
  1279. #define A2 A0+2
  1280. ;; B[0..2]: In: Divisor; Out: Remainder
  1281. #define B0 18
  1282. #define B1 B0+1
  1283. #define B2 B0+2
  1284. ;; C[0..2]: Expand remainder
  1285. #define C0 __zero_reg__
  1286. #define C1 26
  1287. #define C2 25
  1288. ;; Loop counter
  1289. #define r_cnt 21
  1290. #if defined (L_udivmodpsi4)
  1291. ;; R24:R22 = R24:R24 udiv R20:R18
  1292. ;; R20:R18 = R24:R22 umod R20:R18
  1293. ;; Clobbers: R21, R25, R26
  1294. DEFUN __udivmodpsi4
  1295. ; init loop counter
  1296. ldi r_cnt, 24+1
  1297. ; Clear remainder and carry. C0 is already 0
  1298. clr C1
  1299. sub C2, C2
  1300. ; jump to entry point
  1301. rjmp __udivmodpsi4_start
  1302. __udivmodpsi4_loop:
  1303. ; shift dividend into remainder
  1304. rol C0
  1305. rol C1
  1306. rol C2
  1307. ; compare remainder & divisor
  1308. cp C0, B0
  1309. cpc C1, B1
  1310. cpc C2, B2
  1311. brcs __udivmodpsi4_start ; remainder <= divisor
  1312. sub C0, B0 ; restore remainder
  1313. sbc C1, B1
  1314. sbc C2, B2
  1315. __udivmodpsi4_start:
  1316. ; shift dividend (with CARRY)
  1317. rol A0
  1318. rol A1
  1319. rol A2
  1320. ; decrement loop counter
  1321. dec r_cnt
  1322. brne __udivmodpsi4_loop
  1323. com A0
  1324. com A1
  1325. com A2
  1326. ; div/mod results to return registers
  1327. ; remainder
  1328. mov B0, C0
  1329. mov B1, C1
  1330. mov B2, C2
  1331. clr __zero_reg__ ; C0
  1332. ret
  1333. ENDF __udivmodpsi4
  1334. #endif /* defined (L_udivmodpsi4) */
  1335. #if defined (L_divmodpsi4)
  1336. ;; R24:R22 = R24:R22 div R20:R18
  1337. ;; R20:R18 = R24:R22 mod R20:R18
  1338. ;; Clobbers: T, __tmp_reg__, R21, R25, R26
  1339. DEFUN __divmodpsi4
  1340. ; R0.7 will contain the sign of the result:
  1341. ; R0.7 = A.sign ^ B.sign
  1342. mov __tmp_reg__, B2
  1343. ; T-flag = sign of dividend
  1344. bst A2, 7
  1345. brtc 0f
  1346. com __tmp_reg__
  1347. ; Adjust dividend's sign
  1348. rcall __divmodpsi4_negA
  1349. 0:
  1350. ; Adjust divisor's sign
  1351. sbrc B2, 7
  1352. rcall __divmodpsi4_negB
  1353. ; Do the unsigned div/mod
  1354. XCALL __udivmodpsi4
  1355. ; Adjust quotient's sign
  1356. sbrc __tmp_reg__, 7
  1357. rcall __divmodpsi4_negA
  1358. ; Adjust remainder's sign
  1359. brtc __divmodpsi4_end
  1360. __divmodpsi4_negB:
  1361. ; Correct divisor/remainder sign
  1362. com B2
  1363. com B1
  1364. neg B0
  1365. sbci B1, -1
  1366. sbci B2, -1
  1367. ret
  1368. ; Correct dividend/quotient sign
  1369. __divmodpsi4_negA:
  1370. com A2
  1371. com A1
  1372. neg A0
  1373. sbci A1, -1
  1374. sbci A2, -1
  1375. __divmodpsi4_end:
  1376. ret
  1377. ENDF __divmodpsi4
  1378. #endif /* defined (L_divmodpsi4) */
  1379. #undef A0
  1380. #undef A1
  1381. #undef A2
  1382. #undef B0
  1383. #undef B1
  1384. #undef B2
  1385. #undef C0
  1386. #undef C1
  1387. #undef C2
  1388. #undef r_cnt
  1389. /*******************************************************
  1390. Division 32 / 32 => (result + remainder)
  1391. *******************************************************/
  1392. #define r_remHH r31 /* remainder High */
  1393. #define r_remHL r30
  1394. #define r_remH r27
  1395. #define r_remL r26 /* remainder Low */
  1396. /* return: remainder */
  1397. #define r_arg1HH r25 /* dividend High */
  1398. #define r_arg1HL r24
  1399. #define r_arg1H r23
  1400. #define r_arg1L r22 /* dividend Low */
  1401. /* return: quotient */
  1402. #define r_arg2HH r21 /* divisor High */
  1403. #define r_arg2HL r20
  1404. #define r_arg2H r19
  1405. #define r_arg2L r18 /* divisor Low */
  1406. #define r_cnt __zero_reg__ /* loop count (0 after the loop!) */
  1407. #if defined (L_udivmodsi4)
  1408. DEFUN __udivmodsi4
  1409. ldi r_remL, 33 ; init loop counter
  1410. mov r_cnt, r_remL
  1411. sub r_remL,r_remL
  1412. sub r_remH,r_remH ; clear remainder and carry
  1413. mov_l r_remHL, r_remL
  1414. mov_h r_remHH, r_remH
  1415. rjmp __udivmodsi4_ep ; jump to entry point
  1416. __udivmodsi4_loop:
  1417. rol r_remL ; shift dividend into remainder
  1418. rol r_remH
  1419. rol r_remHL
  1420. rol r_remHH
  1421. cp r_remL,r_arg2L ; compare remainder & divisor
  1422. cpc r_remH,r_arg2H
  1423. cpc r_remHL,r_arg2HL
  1424. cpc r_remHH,r_arg2HH
  1425. brcs __udivmodsi4_ep ; remainder <= divisor
  1426. sub r_remL,r_arg2L ; restore remainder
  1427. sbc r_remH,r_arg2H
  1428. sbc r_remHL,r_arg2HL
  1429. sbc r_remHH,r_arg2HH
  1430. __udivmodsi4_ep:
  1431. rol r_arg1L ; shift dividend (with CARRY)
  1432. rol r_arg1H
  1433. rol r_arg1HL
  1434. rol r_arg1HH
  1435. dec r_cnt ; decrement loop counter
  1436. brne __udivmodsi4_loop
  1437. ; __zero_reg__ now restored (r_cnt == 0)
  1438. com r_arg1L
  1439. com r_arg1H
  1440. com r_arg1HL
  1441. com r_arg1HH
  1442. ; div/mod results to return registers, as for the ldiv() function
  1443. mov_l r_arg2L, r_arg1L ; quotient
  1444. mov_h r_arg2H, r_arg1H
  1445. mov_l r_arg2HL, r_arg1HL
  1446. mov_h r_arg2HH, r_arg1HH
  1447. mov_l r_arg1L, r_remL ; remainder
  1448. mov_h r_arg1H, r_remH
  1449. mov_l r_arg1HL, r_remHL
  1450. mov_h r_arg1HH, r_remHH
  1451. ret
  1452. ENDF __udivmodsi4
  1453. #endif /* defined (L_udivmodsi4) */
  1454. #if defined (L_divmodsi4)
  1455. DEFUN __divmodsi4
  1456. mov __tmp_reg__,r_arg2HH
  1457. bst r_arg1HH,7 ; store sign of dividend
  1458. brtc 0f
  1459. com __tmp_reg__ ; r0.7 is sign of result
  1460. XCALL __negsi2 ; dividend negative: negate
  1461. 0:
  1462. sbrc r_arg2HH,7
  1463. rcall __divmodsi4_neg2 ; divisor negative: negate
  1464. XCALL __udivmodsi4 ; do the unsigned div/mod
  1465. sbrc __tmp_reg__, 7 ; correct quotient sign
  1466. rcall __divmodsi4_neg2
  1467. brtc __divmodsi4_exit ; correct remainder sign
  1468. XJMP __negsi2
  1469. __divmodsi4_neg2:
  1470. ;; correct divisor/quotient sign
  1471. com r_arg2HH
  1472. com r_arg2HL
  1473. com r_arg2H
  1474. neg r_arg2L
  1475. sbci r_arg2H,0xff
  1476. sbci r_arg2HL,0xff
  1477. sbci r_arg2HH,0xff
  1478. __divmodsi4_exit:
  1479. ret
  1480. ENDF __divmodsi4
  1481. #endif /* defined (L_divmodsi4) */
  1482. #if defined (L_negsi2)
  1483. ;; (set (reg:SI 22)
  1484. ;; (neg:SI (reg:SI 22)))
  1485. ;; Sets the V flag for signed overflow tests
  1486. DEFUN __negsi2
  1487. NEG4 22
  1488. ret
  1489. ENDF __negsi2
  1490. #endif /* L_negsi2 */
  1491. #undef r_remHH
  1492. #undef r_remHL
  1493. #undef r_remH
  1494. #undef r_remL
  1495. #undef r_arg1HH
  1496. #undef r_arg1HL
  1497. #undef r_arg1H
  1498. #undef r_arg1L
  1499. #undef r_arg2HH
  1500. #undef r_arg2HL
  1501. #undef r_arg2H
  1502. #undef r_arg2L
  1503. #undef r_cnt
  1504. /* *di routines use registers below R19 and won't work with tiny arch
  1505. right now. */
  1506. #if !defined (__AVR_TINY__)
  1507. /*******************************************************
  1508. Division 64 / 64
  1509. Modulo 64 % 64
  1510. *******************************************************/
  1511. ;; Use Speed-optimized Version on "big" Devices, i.e. Devices with
  1512. ;; at least 16k of Program Memory. For smaller Devices, depend
  1513. ;; on MOVW and SP Size. There is a Connexion between SP Size and
  1514. ;; Flash Size so that SP Size can be used to test for Flash Size.
  1515. #if defined (__AVR_HAVE_JMP_CALL__)
  1516. # define SPEED_DIV 8
  1517. #elif defined (__AVR_HAVE_MOVW__) && defined (__AVR_HAVE_SPH__)
  1518. # define SPEED_DIV 16
  1519. #else
  1520. # define SPEED_DIV 0
  1521. #endif
  1522. ;; A[0..7]: In: Dividend;
  1523. ;; Out: Quotient (T = 0)
  1524. ;; Out: Remainder (T = 1)
  1525. #define A0 18
  1526. #define A1 A0+1
  1527. #define A2 A0+2
  1528. #define A3 A0+3
  1529. #define A4 A0+4
  1530. #define A5 A0+5
  1531. #define A6 A0+6
  1532. #define A7 A0+7
  1533. ;; B[0..7]: In: Divisor; Out: Clobber
  1534. #define B0 10
  1535. #define B1 B0+1
  1536. #define B2 B0+2
  1537. #define B3 B0+3
  1538. #define B4 B0+4
  1539. #define B5 B0+5
  1540. #define B6 B0+6
  1541. #define B7 B0+7
  1542. ;; C[0..7]: Expand remainder; Out: Remainder (unused)
  1543. #define C0 8
  1544. #define C1 C0+1
  1545. #define C2 30
  1546. #define C3 C2+1
  1547. #define C4 28
  1548. #define C5 C4+1
  1549. #define C6 26
  1550. #define C7 C6+1
  1551. ;; Holds Signs during Division Routine
  1552. #define SS __tmp_reg__
  1553. ;; Bit-Counter in Division Routine
  1554. #define R_cnt __zero_reg__
  1555. ;; Scratch Register for Negation
  1556. #define NN r31
  1557. #if defined (L_udivdi3)
  1558. ;; R25:R18 = R24:R18 umod R17:R10
  1559. ;; Ordinary ABI-Function
  1560. DEFUN __umoddi3
  1561. set
  1562. rjmp __udivdi3_umoddi3
  1563. ENDF __umoddi3
  1564. ;; R25:R18 = R24:R18 udiv R17:R10
  1565. ;; Ordinary ABI-Function
  1566. DEFUN __udivdi3
  1567. clt
  1568. ENDF __udivdi3
  1569. DEFUN __udivdi3_umoddi3
  1570. push C0
  1571. push C1
  1572. push C4
  1573. push C5
  1574. XCALL __udivmod64
  1575. pop C5
  1576. pop C4
  1577. pop C1
  1578. pop C0
  1579. ret
  1580. ENDF __udivdi3_umoddi3
  1581. #endif /* L_udivdi3 */
  1582. #if defined (L_udivmod64)
  1583. ;; Worker Routine for 64-Bit unsigned Quotient and Remainder Computation
  1584. ;; No Registers saved/restored; the Callers will take Care.
  1585. ;; Preserves B[] and T-flag
  1586. ;; T = 0: Compute Quotient in A[]
  1587. ;; T = 1: Compute Remainder in A[] and shift SS one Bit left
  1588. DEFUN __udivmod64
  1589. ;; Clear Remainder (C6, C7 will follow)
  1590. clr C0
  1591. clr C1
  1592. wmov C2, C0
  1593. wmov C4, C0
  1594. ldi C7, 64
  1595. #if SPEED_DIV == 0 || SPEED_DIV == 16
  1596. ;; Initialize Loop-Counter
  1597. mov R_cnt, C7
  1598. wmov C6, C0
  1599. #endif /* SPEED_DIV */
  1600. #if SPEED_DIV == 8
  1601. push A7
  1602. clr C6
  1603. 1: ;; Compare shifted Devidend against Divisor
  1604. ;; If -- even after Shifting -- it is smaller...
  1605. CP A7,B0 $ cpc C0,B1 $ cpc C1,B2 $ cpc C2,B3
  1606. cpc C3,B4 $ cpc C4,B5 $ cpc C5,B6 $ cpc C6,B7
  1607. brcc 2f
  1608. ;; ...then we can subtract it. Thus, it is legal to shift left
  1609. $ mov C6,C5 $ mov C5,C4 $ mov C4,C3
  1610. mov C3,C2 $ mov C2,C1 $ mov C1,C0 $ mov C0,A7
  1611. mov A7,A6 $ mov A6,A5 $ mov A5,A4 $ mov A4,A3
  1612. mov A3,A2 $ mov A2,A1 $ mov A1,A0 $ clr A0
  1613. ;; 8 Bits are done
  1614. subi C7, 8
  1615. brne 1b
  1616. ;; Shifted 64 Bits: A7 has traveled to C7
  1617. pop C7
  1618. ;; Divisor is greater than Dividend. We have:
  1619. ;; A[] % B[] = A[]
  1620. ;; A[] / B[] = 0
  1621. ;; Thus, we can return immediately
  1622. rjmp 5f
  1623. 2: ;; Initialze Bit-Counter with Number of Bits still to be performed
  1624. mov R_cnt, C7
  1625. ;; Push of A7 is not needed because C7 is still 0
  1626. pop C7
  1627. clr C7
  1628. #elif SPEED_DIV == 16
  1629. ;; Compare shifted Dividend against Divisor
  1630. cp A7, B3
  1631. cpc C0, B4
  1632. cpc C1, B5
  1633. cpc C2, B6
  1634. cpc C3, B7
  1635. brcc 2f
  1636. ;; Divisor is greater than shifted Dividen: We can shift the Dividend
  1637. ;; and it is still smaller than the Divisor --> Shift one 32-Bit Chunk
  1638. wmov C2,A6 $ wmov C0,A4
  1639. wmov A6,A2 $ wmov A4,A0
  1640. wmov A2,C6 $ wmov A0,C4
  1641. ;; Set Bit Counter to 32
  1642. lsr R_cnt
  1643. 2:
  1644. #elif SPEED_DIV
  1645. #error SPEED_DIV = ?
  1646. #endif /* SPEED_DIV */
  1647. ;; The very Division + Remainder Routine
  1648. 3: ;; Left-shift Dividend...
  1649. lsl A0 $ rol A1 $ rol A2 $ rol A3
  1650. rol A4 $ rol A5 $ rol A6 $ rol A7
  1651. ;; ...into Remainder
  1652. rol C0 $ rol C1 $ rol C2 $ rol C3
  1653. rol C4 $ rol C5 $ rol C6 $ rol C7
  1654. ;; Compare Remainder and Divisor
  1655. CP C0,B0 $ cpc C1,B1 $ cpc C2,B2 $ cpc C3,B3
  1656. cpc C4,B4 $ cpc C5,B5 $ cpc C6,B6 $ cpc C7,B7
  1657. brcs 4f
  1658. ;; Divisor fits into Remainder: Subtract it from Remainder...
  1659. SUB C0,B0 $ sbc C1,B1 $ sbc C2,B2 $ sbc C3,B3
  1660. sbc C4,B4 $ sbc C5,B5 $ sbc C6,B6 $ sbc C7,B7
  1661. ;; ...and set according Bit in the upcoming Quotient
  1662. ;; The Bit will travel to its final Position
  1663. ori A0, 1
  1664. 4: ;; This Bit is done
  1665. dec R_cnt
  1666. brne 3b
  1667. ;; __zero_reg__ is 0 again
  1668. ;; T = 0: We are fine with the Quotient in A[]
  1669. ;; T = 1: Copy Remainder to A[]
  1670. 5: brtc 6f
  1671. wmov A0, C0
  1672. wmov A2, C2
  1673. wmov A4, C4
  1674. wmov A6, C6
  1675. ;; Move the Sign of the Result to SS.7
  1676. lsl SS
  1677. 6: ret
  1678. ENDF __udivmod64
  1679. #endif /* L_udivmod64 */
  1680. #if defined (L_divdi3)
  1681. ;; R25:R18 = R24:R18 mod R17:R10
  1682. ;; Ordinary ABI-Function
  1683. DEFUN __moddi3
  1684. set
  1685. rjmp __divdi3_moddi3
  1686. ENDF __moddi3
  1687. ;; R25:R18 = R24:R18 div R17:R10
  1688. ;; Ordinary ABI-Function
  1689. DEFUN __divdi3
  1690. clt
  1691. ENDF __divdi3
  1692. DEFUN __divdi3_moddi3
  1693. #if SPEED_DIV
  1694. mov r31, A7
  1695. or r31, B7
  1696. brmi 0f
  1697. ;; Both Signs are 0: the following Complexitiy is not needed
  1698. XJMP __udivdi3_umoddi3
  1699. #endif /* SPEED_DIV */
  1700. 0: ;; The Prologue
  1701. ;; Save 12 Registers: Y, 17...8
  1702. ;; No Frame needed
  1703. do_prologue_saves 12
  1704. ;; SS.7 will contain the Sign of the Quotient (A.sign * B.sign)
  1705. ;; SS.6 will contain the Sign of the Remainder (A.sign)
  1706. mov SS, A7
  1707. asr SS
  1708. ;; Adjust Dividend's Sign as needed
  1709. #if SPEED_DIV
  1710. ;; Compiling for Speed we know that at least one Sign must be < 0
  1711. ;; Thus, if A[] >= 0 then we know B[] < 0
  1712. brpl 22f
  1713. #else
  1714. brpl 21f
  1715. #endif /* SPEED_DIV */
  1716. XCALL __negdi2
  1717. ;; Adjust Divisor's Sign and SS.7 as needed
  1718. 21: tst B7
  1719. brpl 3f
  1720. 22: ldi NN, 1 << 7
  1721. eor SS, NN
  1722. ldi NN, -1
  1723. com B4 $ com B5 $ com B6 $ com B7
  1724. $ com B1 $ com B2 $ com B3
  1725. NEG B0
  1726. $ sbc B1,NN $ sbc B2,NN $ sbc B3,NN
  1727. sbc B4,NN $ sbc B5,NN $ sbc B6,NN $ sbc B7,NN
  1728. 3: ;; Do the unsigned 64-Bit Division/Modulo (depending on T-flag)
  1729. XCALL __udivmod64
  1730. ;; Adjust Result's Sign
  1731. #ifdef __AVR_ERRATA_SKIP_JMP_CALL__
  1732. tst SS
  1733. brpl 4f
  1734. #else
  1735. sbrc SS, 7
  1736. #endif /* __AVR_HAVE_JMP_CALL__ */
  1737. XCALL __negdi2
  1738. 4: ;; Epilogue: Restore 12 Registers and return
  1739. do_epilogue_restores 12
  1740. ENDF __divdi3_moddi3
  1741. #endif /* L_divdi3 */
  1742. #undef R_cnt
  1743. #undef SS
  1744. #undef NN
  1745. .section .text.libgcc, "ax", @progbits
  1746. #define TT __tmp_reg__
  1747. #if defined (L_adddi3)
  1748. ;; (set (reg:DI 18)
  1749. ;; (plus:DI (reg:DI 18)
  1750. ;; (reg:DI 10)))
  1751. ;; Sets the V flag for signed overflow tests
  1752. ;; Sets the C flag for unsigned overflow tests
  1753. DEFUN __adddi3
  1754. ADD A0,B0 $ adc A1,B1 $ adc A2,B2 $ adc A3,B3
  1755. adc A4,B4 $ adc A5,B5 $ adc A6,B6 $ adc A7,B7
  1756. ret
  1757. ENDF __adddi3
  1758. #endif /* L_adddi3 */
  1759. #if defined (L_adddi3_s8)
  1760. ;; (set (reg:DI 18)
  1761. ;; (plus:DI (reg:DI 18)
  1762. ;; (sign_extend:SI (reg:QI 26))))
  1763. ;; Sets the V flag for signed overflow tests
  1764. ;; Sets the C flag for unsigned overflow tests provided 0 <= R26 < 128
  1765. DEFUN __adddi3_s8
  1766. clr TT
  1767. sbrc r26, 7
  1768. com TT
  1769. ADD A0,r26 $ adc A1,TT $ adc A2,TT $ adc A3,TT
  1770. adc A4,TT $ adc A5,TT $ adc A6,TT $ adc A7,TT
  1771. ret
  1772. ENDF __adddi3_s8
  1773. #endif /* L_adddi3_s8 */
  1774. #if defined (L_subdi3)
  1775. ;; (set (reg:DI 18)
  1776. ;; (minus:DI (reg:DI 18)
  1777. ;; (reg:DI 10)))
  1778. ;; Sets the V flag for signed overflow tests
  1779. ;; Sets the C flag for unsigned overflow tests
  1780. DEFUN __subdi3
  1781. SUB A0,B0 $ sbc A1,B1 $ sbc A2,B2 $ sbc A3,B3
  1782. sbc A4,B4 $ sbc A5,B5 $ sbc A6,B6 $ sbc A7,B7
  1783. ret
  1784. ENDF __subdi3
  1785. #endif /* L_subdi3 */
  1786. #if defined (L_cmpdi2)
  1787. ;; (set (cc0)
  1788. ;; (compare (reg:DI 18)
  1789. ;; (reg:DI 10)))
  1790. DEFUN __cmpdi2
  1791. CP A0,B0 $ cpc A1,B1 $ cpc A2,B2 $ cpc A3,B3
  1792. cpc A4,B4 $ cpc A5,B5 $ cpc A6,B6 $ cpc A7,B7
  1793. ret
  1794. ENDF __cmpdi2
  1795. #endif /* L_cmpdi2 */
  1796. #if defined (L_cmpdi2_s8)
  1797. ;; (set (cc0)
  1798. ;; (compare (reg:DI 18)
  1799. ;; (sign_extend:SI (reg:QI 26))))
  1800. DEFUN __cmpdi2_s8
  1801. clr TT
  1802. sbrc r26, 7
  1803. com TT
  1804. CP A0,r26 $ cpc A1,TT $ cpc A2,TT $ cpc A3,TT
  1805. cpc A4,TT $ cpc A5,TT $ cpc A6,TT $ cpc A7,TT
  1806. ret
  1807. ENDF __cmpdi2_s8
  1808. #endif /* L_cmpdi2_s8 */
  1809. #if defined (L_negdi2)
  1810. ;; (set (reg:DI 18)
  1811. ;; (neg:DI (reg:DI 18)))
  1812. ;; Sets the V flag for signed overflow tests
  1813. DEFUN __negdi2
  1814. com A4 $ com A5 $ com A6 $ com A7
  1815. $ com A1 $ com A2 $ com A3
  1816. NEG A0
  1817. $ sbci A1,-1 $ sbci A2,-1 $ sbci A3,-1
  1818. sbci A4,-1 $ sbci A5,-1 $ sbci A6,-1 $ sbci A7,-1
  1819. ret
  1820. ENDF __negdi2
  1821. #endif /* L_negdi2 */
  1822. #undef TT
  1823. #undef C7
  1824. #undef C6
  1825. #undef C5
  1826. #undef C4
  1827. #undef C3
  1828. #undef C2
  1829. #undef C1
  1830. #undef C0
  1831. #undef B7
  1832. #undef B6
  1833. #undef B5
  1834. #undef B4
  1835. #undef B3
  1836. #undef B2
  1837. #undef B1
  1838. #undef B0
  1839. #undef A7
  1840. #undef A6
  1841. #undef A5
  1842. #undef A4
  1843. #undef A3
  1844. #undef A2
  1845. #undef A1
  1846. #undef A0
  1847. #endif /* !defined (__AVR_TINY__) */
  1848. .section .text.libgcc.prologue, "ax", @progbits
  1849. /**********************************
  1850. * This is a prologue subroutine
  1851. **********************************/
  1852. #if !defined (__AVR_TINY__)
  1853. #if defined (L_prologue)
  1854. ;; This function does not clobber T-flag; 64-bit division relies on it
  1855. DEFUN __prologue_saves__
  1856. push r2
  1857. push r3
  1858. push r4
  1859. push r5
  1860. push r6
  1861. push r7
  1862. push r8
  1863. push r9
  1864. push r10
  1865. push r11
  1866. push r12
  1867. push r13
  1868. push r14
  1869. push r15
  1870. push r16
  1871. push r17
  1872. push r28
  1873. push r29
  1874. #if !defined (__AVR_HAVE_SPH__)
  1875. in r28,__SP_L__
  1876. sub r28,r26
  1877. out __SP_L__,r28
  1878. clr r29
  1879. #elif defined (__AVR_XMEGA__)
  1880. in r28,__SP_L__
  1881. in r29,__SP_H__
  1882. sub r28,r26
  1883. sbc r29,r27
  1884. out __SP_L__,r28
  1885. out __SP_H__,r29
  1886. #else
  1887. in r28,__SP_L__
  1888. in r29,__SP_H__
  1889. sub r28,r26
  1890. sbc r29,r27
  1891. in __tmp_reg__,__SREG__
  1892. cli
  1893. out __SP_H__,r29
  1894. out __SREG__,__tmp_reg__
  1895. out __SP_L__,r28
  1896. #endif /* #SP = 8/16 */
  1897. XIJMP
  1898. ENDF __prologue_saves__
  1899. #endif /* defined (L_prologue) */
  1900. /*
  1901. * This is an epilogue subroutine
  1902. */
  1903. #if defined (L_epilogue)
  1904. DEFUN __epilogue_restores__
  1905. ldd r2,Y+18
  1906. ldd r3,Y+17
  1907. ldd r4,Y+16
  1908. ldd r5,Y+15
  1909. ldd r6,Y+14
  1910. ldd r7,Y+13
  1911. ldd r8,Y+12
  1912. ldd r9,Y+11
  1913. ldd r10,Y+10
  1914. ldd r11,Y+9
  1915. ldd r12,Y+8
  1916. ldd r13,Y+7
  1917. ldd r14,Y+6
  1918. ldd r15,Y+5
  1919. ldd r16,Y+4
  1920. ldd r17,Y+3
  1921. ldd r26,Y+2
  1922. #if !defined (__AVR_HAVE_SPH__)
  1923. ldd r29,Y+1
  1924. add r28,r30
  1925. out __SP_L__,r28
  1926. mov r28, r26
  1927. #elif defined (__AVR_XMEGA__)
  1928. ldd r27,Y+1
  1929. add r28,r30
  1930. adc r29,__zero_reg__
  1931. out __SP_L__,r28
  1932. out __SP_H__,r29
  1933. wmov 28, 26
  1934. #else
  1935. ldd r27,Y+1
  1936. add r28,r30
  1937. adc r29,__zero_reg__
  1938. in __tmp_reg__,__SREG__
  1939. cli
  1940. out __SP_H__,r29
  1941. out __SREG__,__tmp_reg__
  1942. out __SP_L__,r28
  1943. mov_l r28, r26
  1944. mov_h r29, r27
  1945. #endif /* #SP = 8/16 */
  1946. ret
  1947. ENDF __epilogue_restores__
  1948. #endif /* defined (L_epilogue) */
  1949. #endif /* !defined (__AVR_TINY__) */
  1950. #ifdef L_exit
  1951. .section .fini9,"ax",@progbits
  1952. DEFUN _exit
  1953. .weak exit
  1954. exit:
  1955. ENDF _exit
  1956. /* Code from .fini8 ... .fini1 sections inserted by ld script. */
  1957. .section .fini0,"ax",@progbits
  1958. cli
  1959. __stop_program:
  1960. rjmp __stop_program
  1961. #endif /* defined (L_exit) */
  1962. #ifdef L_cleanup
  1963. .weak _cleanup
  1964. .func _cleanup
  1965. _cleanup:
  1966. ret
  1967. .endfunc
  1968. #endif /* defined (L_cleanup) */
  1969. .section .text.libgcc, "ax", @progbits
  1970. #ifdef L_tablejump2
  1971. DEFUN __tablejump2__
  1972. lsl r30
  1973. rol r31
  1974. #if defined (__AVR_HAVE_EIJMP_EICALL__)
  1975. ;; Word address of gs() jumptable entry in R24:Z
  1976. rol r24
  1977. out __RAMPZ__, r24
  1978. #elif defined (__AVR_HAVE_ELPM__)
  1979. ;; Word address of jumptable entry in Z
  1980. clr __tmp_reg__
  1981. rol __tmp_reg__
  1982. out __RAMPZ__, __tmp_reg__
  1983. #endif
  1984. ;; Read word address from jumptable and jump
  1985. #if defined (__AVR_HAVE_ELPMX__)
  1986. elpm __tmp_reg__, Z+
  1987. elpm r31, Z
  1988. mov r30, __tmp_reg__
  1989. #ifdef __AVR_HAVE_RAMPD__
  1990. ;; Reset RAMPZ to 0 so that EBI devices don't read garbage from RAM
  1991. out __RAMPZ__, __zero_reg__
  1992. #endif /* RAMPD */
  1993. XIJMP
  1994. #elif defined (__AVR_HAVE_ELPM__)
  1995. elpm
  1996. push r0
  1997. adiw r30, 1
  1998. elpm
  1999. push r0
  2000. ret
  2001. #elif defined (__AVR_HAVE_LPMX__)
  2002. lpm __tmp_reg__, Z+
  2003. lpm r31, Z
  2004. mov r30, __tmp_reg__
  2005. ijmp
  2006. #elif defined (__AVR_TINY__)
  2007. wsubi 30, -(__AVR_TINY_PM_BASE_ADDRESS__) ; Add PM offset to Z
  2008. ld __tmp_reg__, Z+
  2009. ld r31, Z ; Use ld instead of lpm to load Z
  2010. mov r30, __tmp_reg__
  2011. ijmp
  2012. #else
  2013. lpm
  2014. push r0
  2015. adiw r30, 1
  2016. lpm
  2017. push r0
  2018. ret
  2019. #endif
  2020. ENDF __tablejump2__
  2021. #endif /* L_tablejump2 */
  2022. #if defined(__AVR_TINY__)
  2023. #ifdef L_copy_data
  2024. .section .init4,"ax",@progbits
  2025. .global __do_copy_data
  2026. __do_copy_data:
  2027. ldi r18, hi8(__data_end)
  2028. ldi r26, lo8(__data_start)
  2029. ldi r27, hi8(__data_start)
  2030. ldi r30, lo8(__data_load_start + __AVR_TINY_PM_BASE_ADDRESS__)
  2031. ldi r31, hi8(__data_load_start + __AVR_TINY_PM_BASE_ADDRESS__)
  2032. rjmp .L__do_copy_data_start
  2033. .L__do_copy_data_loop:
  2034. ld r19, z+
  2035. st X+, r19
  2036. .L__do_copy_data_start:
  2037. cpi r26, lo8(__data_end)
  2038. cpc r27, r18
  2039. brne .L__do_copy_data_loop
  2040. #endif
  2041. #else
  2042. #ifdef L_copy_data
  2043. .section .init4,"ax",@progbits
  2044. DEFUN __do_copy_data
  2045. #if defined(__AVR_HAVE_ELPMX__)
  2046. ldi r17, hi8(__data_end)
  2047. ldi r26, lo8(__data_start)
  2048. ldi r27, hi8(__data_start)
  2049. ldi r30, lo8(__data_load_start)
  2050. ldi r31, hi8(__data_load_start)
  2051. ldi r16, hh8(__data_load_start)
  2052. out __RAMPZ__, r16
  2053. rjmp .L__do_copy_data_start
  2054. .L__do_copy_data_loop:
  2055. elpm r0, Z+
  2056. st X+, r0
  2057. .L__do_copy_data_start:
  2058. cpi r26, lo8(__data_end)
  2059. cpc r27, r17
  2060. brne .L__do_copy_data_loop
  2061. #elif !defined(__AVR_HAVE_ELPMX__) && defined(__AVR_HAVE_ELPM__)
  2062. ldi r17, hi8(__data_end)
  2063. ldi r26, lo8(__data_start)
  2064. ldi r27, hi8(__data_start)
  2065. ldi r30, lo8(__data_load_start)
  2066. ldi r31, hi8(__data_load_start)
  2067. ldi r16, hh8(__data_load_start - 0x10000)
  2068. .L__do_copy_data_carry:
  2069. inc r16
  2070. out __RAMPZ__, r16
  2071. rjmp .L__do_copy_data_start
  2072. .L__do_copy_data_loop:
  2073. elpm
  2074. st X+, r0
  2075. adiw r30, 1
  2076. brcs .L__do_copy_data_carry
  2077. .L__do_copy_data_start:
  2078. cpi r26, lo8(__data_end)
  2079. cpc r27, r17
  2080. brne .L__do_copy_data_loop
  2081. #elif !defined(__AVR_HAVE_ELPMX__) && !defined(__AVR_HAVE_ELPM__)
  2082. ldi r17, hi8(__data_end)
  2083. ldi r26, lo8(__data_start)
  2084. ldi r27, hi8(__data_start)
  2085. ldi r30, lo8(__data_load_start)
  2086. ldi r31, hi8(__data_load_start)
  2087. rjmp .L__do_copy_data_start
  2088. .L__do_copy_data_loop:
  2089. #if defined (__AVR_HAVE_LPMX__)
  2090. lpm r0, Z+
  2091. #else
  2092. lpm
  2093. adiw r30, 1
  2094. #endif
  2095. st X+, r0
  2096. .L__do_copy_data_start:
  2097. cpi r26, lo8(__data_end)
  2098. cpc r27, r17
  2099. brne .L__do_copy_data_loop
  2100. #endif /* !defined(__AVR_HAVE_ELPMX__) && !defined(__AVR_HAVE_ELPM__) */
  2101. #if defined (__AVR_HAVE_ELPM__) && defined (__AVR_HAVE_RAMPD__)
  2102. ;; Reset RAMPZ to 0 so that EBI devices don't read garbage from RAM
  2103. out __RAMPZ__, __zero_reg__
  2104. #endif /* ELPM && RAMPD */
  2105. ENDF __do_copy_data
  2106. #endif /* L_copy_data */
  2107. #endif /* !defined (__AVR_TINY__) */
  2108. /* __do_clear_bss is only necessary if there is anything in .bss section. */
  2109. #ifdef L_clear_bss
  2110. .section .init4,"ax",@progbits
  2111. DEFUN __do_clear_bss
  2112. ldi r18, hi8(__bss_end)
  2113. ldi r26, lo8(__bss_start)
  2114. ldi r27, hi8(__bss_start)
  2115. rjmp .do_clear_bss_start
  2116. .do_clear_bss_loop:
  2117. st X+, __zero_reg__
  2118. .do_clear_bss_start:
  2119. cpi r26, lo8(__bss_end)
  2120. cpc r27, r18
  2121. brne .do_clear_bss_loop
  2122. ENDF __do_clear_bss
  2123. #endif /* L_clear_bss */
  2124. /* __do_global_ctors and __do_global_dtors are only necessary
  2125. if there are any constructors/destructors. */
  2126. #if defined(__AVR_TINY__)
  2127. #define cdtors_tst_reg r18
  2128. #else
  2129. #define cdtors_tst_reg r17
  2130. #endif
  2131. #ifdef L_ctors
  2132. .section .init6,"ax",@progbits
  2133. DEFUN __do_global_ctors
  2134. ldi cdtors_tst_reg, pm_hi8(__ctors_start)
  2135. ldi r28, pm_lo8(__ctors_end)
  2136. ldi r29, pm_hi8(__ctors_end)
  2137. #ifdef __AVR_HAVE_EIJMP_EICALL__
  2138. ldi r16, pm_hh8(__ctors_end)
  2139. #endif /* HAVE_EIJMP */
  2140. rjmp .L__do_global_ctors_start
  2141. .L__do_global_ctors_loop:
  2142. wsubi 28, 1
  2143. #ifdef __AVR_HAVE_EIJMP_EICALL__
  2144. sbc r16, __zero_reg__
  2145. mov r24, r16
  2146. #endif /* HAVE_EIJMP */
  2147. mov_h r31, r29
  2148. mov_l r30, r28
  2149. XCALL __tablejump2__
  2150. .L__do_global_ctors_start:
  2151. cpi r28, pm_lo8(__ctors_start)
  2152. cpc r29, cdtors_tst_reg
  2153. #ifdef __AVR_HAVE_EIJMP_EICALL__
  2154. ldi r24, pm_hh8(__ctors_start)
  2155. cpc r16, r24
  2156. #endif /* HAVE_EIJMP */
  2157. brne .L__do_global_ctors_loop
  2158. ENDF __do_global_ctors
  2159. #endif /* L_ctors */
  2160. #ifdef L_dtors
  2161. .section .fini6,"ax",@progbits
  2162. DEFUN __do_global_dtors
  2163. ldi cdtors_tst_reg, pm_hi8(__dtors_end)
  2164. ldi r28, pm_lo8(__dtors_start)
  2165. ldi r29, pm_hi8(__dtors_start)
  2166. #ifdef __AVR_HAVE_EIJMP_EICALL__
  2167. ldi r16, pm_hh8(__dtors_start)
  2168. #endif /* HAVE_EIJMP */
  2169. rjmp .L__do_global_dtors_start
  2170. .L__do_global_dtors_loop:
  2171. #ifdef __AVR_HAVE_EIJMP_EICALL__
  2172. mov r24, r16
  2173. #endif /* HAVE_EIJMP */
  2174. mov_h r31, r29
  2175. mov_l r30, r28
  2176. XCALL __tablejump2__
  2177. waddi 28, 1
  2178. #ifdef __AVR_HAVE_EIJMP_EICALL__
  2179. adc r16, __zero_reg__
  2180. #endif /* HAVE_EIJMP */
  2181. .L__do_global_dtors_start:
  2182. cpi r28, pm_lo8(__dtors_end)
  2183. cpc r29, cdtors_tst_reg
  2184. #ifdef __AVR_HAVE_EIJMP_EICALL__
  2185. ldi r24, pm_hh8(__dtors_end)
  2186. cpc r16, r24
  2187. #endif /* HAVE_EIJMP */
  2188. brne .L__do_global_dtors_loop
  2189. ENDF __do_global_dtors
  2190. #endif /* L_dtors */
  2191. #undef cdtors_tst_reg
  2192. .section .text.libgcc, "ax", @progbits
  2193. #if !defined (__AVR_TINY__)
  2194. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2195. ;; Loading n bytes from Flash; n = 3,4
  2196. ;; R22... = Flash[Z]
  2197. ;; Clobbers: __tmp_reg__
  2198. #if (defined (L_load_3) \
  2199. || defined (L_load_4)) \
  2200. && !defined (__AVR_HAVE_LPMX__)
  2201. ;; Destination
  2202. #define D0 22
  2203. #define D1 D0+1
  2204. #define D2 D0+2
  2205. #define D3 D0+3
  2206. .macro .load dest, n
  2207. lpm
  2208. mov \dest, r0
  2209. .if \dest != D0+\n-1
  2210. adiw r30, 1
  2211. .else
  2212. sbiw r30, \n-1
  2213. .endif
  2214. .endm
  2215. #if defined (L_load_3)
  2216. DEFUN __load_3
  2217. push D3
  2218. XCALL __load_4
  2219. pop D3
  2220. ret
  2221. ENDF __load_3
  2222. #endif /* L_load_3 */
  2223. #if defined (L_load_4)
  2224. DEFUN __load_4
  2225. .load D0, 4
  2226. .load D1, 4
  2227. .load D2, 4
  2228. .load D3, 4
  2229. ret
  2230. ENDF __load_4
  2231. #endif /* L_load_4 */
  2232. #endif /* L_load_3 || L_load_3 */
  2233. #endif /* !defined (__AVR_TINY__) */
  2234. #if !defined (__AVR_TINY__)
  2235. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2236. ;; Loading n bytes from Flash or RAM; n = 1,2,3,4
  2237. ;; R22... = Flash[R21:Z] or RAM[Z] depending on R21.7
  2238. ;; Clobbers: __tmp_reg__, R21, R30, R31
  2239. #if (defined (L_xload_1) \
  2240. || defined (L_xload_2) \
  2241. || defined (L_xload_3) \
  2242. || defined (L_xload_4))
  2243. ;; Destination
  2244. #define D0 22
  2245. #define D1 D0+1
  2246. #define D2 D0+2
  2247. #define D3 D0+3
  2248. ;; Register containing bits 16+ of the address
  2249. #define HHI8 21
  2250. .macro .xload dest, n
  2251. #if defined (__AVR_HAVE_ELPMX__)
  2252. elpm \dest, Z+
  2253. #elif defined (__AVR_HAVE_ELPM__)
  2254. elpm
  2255. mov \dest, r0
  2256. .if \dest != D0+\n-1
  2257. adiw r30, 1
  2258. adc HHI8, __zero_reg__
  2259. out __RAMPZ__, HHI8
  2260. .endif
  2261. #elif defined (__AVR_HAVE_LPMX__)
  2262. lpm \dest, Z+
  2263. #else
  2264. lpm
  2265. mov \dest, r0
  2266. .if \dest != D0+\n-1
  2267. adiw r30, 1
  2268. .endif
  2269. #endif
  2270. #if defined (__AVR_HAVE_ELPM__) && defined (__AVR_HAVE_RAMPD__)
  2271. .if \dest == D0+\n-1
  2272. ;; Reset RAMPZ to 0 so that EBI devices don't read garbage from RAM
  2273. out __RAMPZ__, __zero_reg__
  2274. .endif
  2275. #endif
  2276. .endm ; .xload
  2277. #if defined (L_xload_1)
  2278. DEFUN __xload_1
  2279. #if defined (__AVR_HAVE_LPMX__) && !defined (__AVR_HAVE_ELPM__)
  2280. sbrc HHI8, 7
  2281. ld D0, Z
  2282. sbrs HHI8, 7
  2283. lpm D0, Z
  2284. ret
  2285. #else
  2286. sbrc HHI8, 7
  2287. rjmp 1f
  2288. #if defined (__AVR_HAVE_ELPM__)
  2289. out __RAMPZ__, HHI8
  2290. #endif /* __AVR_HAVE_ELPM__ */
  2291. .xload D0, 1
  2292. ret
  2293. 1: ld D0, Z
  2294. ret
  2295. #endif /* LPMx && ! ELPM */
  2296. ENDF __xload_1
  2297. #endif /* L_xload_1 */
  2298. #if defined (L_xload_2)
  2299. DEFUN __xload_2
  2300. sbrc HHI8, 7
  2301. rjmp 1f
  2302. #if defined (__AVR_HAVE_ELPM__)
  2303. out __RAMPZ__, HHI8
  2304. #endif /* __AVR_HAVE_ELPM__ */
  2305. .xload D0, 2
  2306. .xload D1, 2
  2307. ret
  2308. 1: ld D0, Z+
  2309. ld D1, Z+
  2310. ret
  2311. ENDF __xload_2
  2312. #endif /* L_xload_2 */
  2313. #if defined (L_xload_3)
  2314. DEFUN __xload_3
  2315. sbrc HHI8, 7
  2316. rjmp 1f
  2317. #if defined (__AVR_HAVE_ELPM__)
  2318. out __RAMPZ__, HHI8
  2319. #endif /* __AVR_HAVE_ELPM__ */
  2320. .xload D0, 3
  2321. .xload D1, 3
  2322. .xload D2, 3
  2323. ret
  2324. 1: ld D0, Z+
  2325. ld D1, Z+
  2326. ld D2, Z+
  2327. ret
  2328. ENDF __xload_3
  2329. #endif /* L_xload_3 */
  2330. #if defined (L_xload_4)
  2331. DEFUN __xload_4
  2332. sbrc HHI8, 7
  2333. rjmp 1f
  2334. #if defined (__AVR_HAVE_ELPM__)
  2335. out __RAMPZ__, HHI8
  2336. #endif /* __AVR_HAVE_ELPM__ */
  2337. .xload D0, 4
  2338. .xload D1, 4
  2339. .xload D2, 4
  2340. .xload D3, 4
  2341. ret
  2342. 1: ld D0, Z+
  2343. ld D1, Z+
  2344. ld D2, Z+
  2345. ld D3, Z+
  2346. ret
  2347. ENDF __xload_4
  2348. #endif /* L_xload_4 */
  2349. #endif /* L_xload_{1|2|3|4} */
  2350. #endif /* if !defined (__AVR_TINY__) */
  2351. #if !defined (__AVR_TINY__)
  2352. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2353. ;; memcopy from Address Space __pgmx to RAM
  2354. ;; R23:Z = Source Address
  2355. ;; X = Destination Address
  2356. ;; Clobbers: __tmp_reg__, R23, R24, R25, X, Z
  2357. #if defined (L_movmemx)
  2358. #define HHI8 23
  2359. #define LOOP 24
  2360. DEFUN __movmemx_qi
  2361. ;; #Bytes to copy fity in 8 Bits (1..255)
  2362. ;; Zero-extend Loop Counter
  2363. clr LOOP+1
  2364. ;; FALLTHRU
  2365. ENDF __movmemx_qi
  2366. DEFUN __movmemx_hi
  2367. ;; Read from where?
  2368. sbrc HHI8, 7
  2369. rjmp 1f
  2370. ;; Read from Flash
  2371. #if defined (__AVR_HAVE_ELPM__)
  2372. out __RAMPZ__, HHI8
  2373. #endif
  2374. 0: ;; Load 1 Byte from Flash...
  2375. #if defined (__AVR_HAVE_ELPMX__)
  2376. elpm r0, Z+
  2377. #elif defined (__AVR_HAVE_ELPM__)
  2378. elpm
  2379. adiw r30, 1
  2380. adc HHI8, __zero_reg__
  2381. out __RAMPZ__, HHI8
  2382. #elif defined (__AVR_HAVE_LPMX__)
  2383. lpm r0, Z+
  2384. #else
  2385. lpm
  2386. adiw r30, 1
  2387. #endif
  2388. ;; ...and store that Byte to RAM Destination
  2389. st X+, r0
  2390. sbiw LOOP, 1
  2391. brne 0b
  2392. #if defined (__AVR_HAVE_ELPM__) && defined (__AVR_HAVE_RAMPD__)
  2393. ;; Reset RAMPZ to 0 so that EBI devices don't read garbage from RAM
  2394. out __RAMPZ__, __zero_reg__
  2395. #endif /* ELPM && RAMPD */
  2396. ret
  2397. ;; Read from RAM
  2398. 1: ;; Read 1 Byte from RAM...
  2399. ld r0, Z+
  2400. ;; and store that Byte to RAM Destination
  2401. st X+, r0
  2402. sbiw LOOP, 1
  2403. brne 1b
  2404. ret
  2405. ENDF __movmemx_hi
  2406. #undef HHI8
  2407. #undef LOOP
  2408. #endif /* L_movmemx */
  2409. #endif /* !defined (__AVR_TINY__) */
  2410. .section .text.libgcc.builtins, "ax", @progbits
  2411. /**********************************
  2412. * Find first set Bit (ffs)
  2413. **********************************/
  2414. #if defined (L_ffssi2)
  2415. ;; find first set bit
  2416. ;; r25:r24 = ffs32 (r25:r22)
  2417. ;; clobbers: r22, r26
  2418. DEFUN __ffssi2
  2419. clr r26
  2420. tst r22
  2421. brne 1f
  2422. subi r26, -8
  2423. or r22, r23
  2424. brne 1f
  2425. subi r26, -8
  2426. or r22, r24
  2427. brne 1f
  2428. subi r26, -8
  2429. or r22, r25
  2430. brne 1f
  2431. ret
  2432. 1: mov r24, r22
  2433. XJMP __loop_ffsqi2
  2434. ENDF __ffssi2
  2435. #endif /* defined (L_ffssi2) */
  2436. #if defined (L_ffshi2)
  2437. ;; find first set bit
  2438. ;; r25:r24 = ffs16 (r25:r24)
  2439. ;; clobbers: r26
  2440. DEFUN __ffshi2
  2441. clr r26
  2442. #ifdef __AVR_ERRATA_SKIP_JMP_CALL__
  2443. ;; Some cores have problem skipping 2-word instruction
  2444. tst r24
  2445. breq 2f
  2446. #else
  2447. cpse r24, __zero_reg__
  2448. #endif /* __AVR_HAVE_JMP_CALL__ */
  2449. 1: XJMP __loop_ffsqi2
  2450. 2: ldi r26, 8
  2451. or r24, r25
  2452. brne 1b
  2453. ret
  2454. ENDF __ffshi2
  2455. #endif /* defined (L_ffshi2) */
  2456. #if defined (L_loop_ffsqi2)
  2457. ;; Helper for ffshi2, ffssi2
  2458. ;; r25:r24 = r26 + zero_extend16 (ffs8(r24))
  2459. ;; r24 must be != 0
  2460. ;; clobbers: r26
  2461. DEFUN __loop_ffsqi2
  2462. inc r26
  2463. lsr r24
  2464. brcc __loop_ffsqi2
  2465. mov r24, r26
  2466. clr r25
  2467. ret
  2468. ENDF __loop_ffsqi2
  2469. #endif /* defined (L_loop_ffsqi2) */
  2470. /**********************************
  2471. * Count trailing Zeros (ctz)
  2472. **********************************/
  2473. #if defined (L_ctzsi2)
  2474. ;; count trailing zeros
  2475. ;; r25:r24 = ctz32 (r25:r22)
  2476. ;; clobbers: r26, r22
  2477. ;; ctz(0) = 255
  2478. ;; Note that ctz(0) in undefined for GCC
  2479. DEFUN __ctzsi2
  2480. XCALL __ffssi2
  2481. dec r24
  2482. ret
  2483. ENDF __ctzsi2
  2484. #endif /* defined (L_ctzsi2) */
  2485. #if defined (L_ctzhi2)
  2486. ;; count trailing zeros
  2487. ;; r25:r24 = ctz16 (r25:r24)
  2488. ;; clobbers: r26
  2489. ;; ctz(0) = 255
  2490. ;; Note that ctz(0) in undefined for GCC
  2491. DEFUN __ctzhi2
  2492. XCALL __ffshi2
  2493. dec r24
  2494. ret
  2495. ENDF __ctzhi2
  2496. #endif /* defined (L_ctzhi2) */
  2497. /**********************************
  2498. * Count leading Zeros (clz)
  2499. **********************************/
  2500. #if defined (L_clzdi2)
  2501. ;; count leading zeros
  2502. ;; r25:r24 = clz64 (r25:r18)
  2503. ;; clobbers: r22, r23, r26
  2504. DEFUN __clzdi2
  2505. XCALL __clzsi2
  2506. sbrs r24, 5
  2507. ret
  2508. mov_l r22, r18
  2509. mov_h r23, r19
  2510. mov_l r24, r20
  2511. mov_h r25, r21
  2512. XCALL __clzsi2
  2513. subi r24, -32
  2514. ret
  2515. ENDF __clzdi2
  2516. #endif /* defined (L_clzdi2) */
  2517. #if defined (L_clzsi2)
  2518. ;; count leading zeros
  2519. ;; r25:r24 = clz32 (r25:r22)
  2520. ;; clobbers: r26
  2521. DEFUN __clzsi2
  2522. XCALL __clzhi2
  2523. sbrs r24, 4
  2524. ret
  2525. mov_l r24, r22
  2526. mov_h r25, r23
  2527. XCALL __clzhi2
  2528. subi r24, -16
  2529. ret
  2530. ENDF __clzsi2
  2531. #endif /* defined (L_clzsi2) */
  2532. #if defined (L_clzhi2)
  2533. ;; count leading zeros
  2534. ;; r25:r24 = clz16 (r25:r24)
  2535. ;; clobbers: r26
  2536. DEFUN __clzhi2
  2537. clr r26
  2538. tst r25
  2539. brne 1f
  2540. subi r26, -8
  2541. or r25, r24
  2542. brne 1f
  2543. ldi r24, 16
  2544. ret
  2545. 1: cpi r25, 16
  2546. brsh 3f
  2547. subi r26, -3
  2548. swap r25
  2549. 2: inc r26
  2550. 3: lsl r25
  2551. brcc 2b
  2552. mov r24, r26
  2553. clr r25
  2554. ret
  2555. ENDF __clzhi2
  2556. #endif /* defined (L_clzhi2) */
  2557. /**********************************
  2558. * Parity
  2559. **********************************/
  2560. #if defined (L_paritydi2)
  2561. ;; r25:r24 = parity64 (r25:r18)
  2562. ;; clobbers: __tmp_reg__
  2563. DEFUN __paritydi2
  2564. eor r24, r18
  2565. eor r24, r19
  2566. eor r24, r20
  2567. eor r24, r21
  2568. XJMP __paritysi2
  2569. ENDF __paritydi2
  2570. #endif /* defined (L_paritydi2) */
  2571. #if defined (L_paritysi2)
  2572. ;; r25:r24 = parity32 (r25:r22)
  2573. ;; clobbers: __tmp_reg__
  2574. DEFUN __paritysi2
  2575. eor r24, r22
  2576. eor r24, r23
  2577. XJMP __parityhi2
  2578. ENDF __paritysi2
  2579. #endif /* defined (L_paritysi2) */
  2580. #if defined (L_parityhi2)
  2581. ;; r25:r24 = parity16 (r25:r24)
  2582. ;; clobbers: __tmp_reg__
  2583. DEFUN __parityhi2
  2584. eor r24, r25
  2585. ;; FALLTHRU
  2586. ENDF __parityhi2
  2587. ;; r25:r24 = parity8 (r24)
  2588. ;; clobbers: __tmp_reg__
  2589. DEFUN __parityqi2
  2590. ;; parity is in r24[0..7]
  2591. mov __tmp_reg__, r24
  2592. swap __tmp_reg__
  2593. eor r24, __tmp_reg__
  2594. ;; parity is in r24[0..3]
  2595. subi r24, -4
  2596. andi r24, -5
  2597. subi r24, -6
  2598. ;; parity is in r24[0,3]
  2599. sbrc r24, 3
  2600. inc r24
  2601. ;; parity is in r24[0]
  2602. andi r24, 1
  2603. clr r25
  2604. ret
  2605. ENDF __parityqi2
  2606. #endif /* defined (L_parityhi2) */
  2607. /**********************************
  2608. * Population Count
  2609. **********************************/
  2610. #if defined (L_popcounthi2)
  2611. ;; population count
  2612. ;; r25:r24 = popcount16 (r25:r24)
  2613. ;; clobbers: __tmp_reg__
  2614. DEFUN __popcounthi2
  2615. XCALL __popcountqi2
  2616. push r24
  2617. mov r24, r25
  2618. XCALL __popcountqi2
  2619. clr r25
  2620. ;; FALLTHRU
  2621. ENDF __popcounthi2
  2622. DEFUN __popcounthi2_tail
  2623. pop __tmp_reg__
  2624. add r24, __tmp_reg__
  2625. ret
  2626. ENDF __popcounthi2_tail
  2627. #endif /* defined (L_popcounthi2) */
  2628. #if defined (L_popcountsi2)
  2629. ;; population count
  2630. ;; r25:r24 = popcount32 (r25:r22)
  2631. ;; clobbers: __tmp_reg__
  2632. DEFUN __popcountsi2
  2633. XCALL __popcounthi2
  2634. push r24
  2635. mov_l r24, r22
  2636. mov_h r25, r23
  2637. XCALL __popcounthi2
  2638. XJMP __popcounthi2_tail
  2639. ENDF __popcountsi2
  2640. #endif /* defined (L_popcountsi2) */
  2641. #if defined (L_popcountdi2)
  2642. ;; population count
  2643. ;; r25:r24 = popcount64 (r25:r18)
  2644. ;; clobbers: r22, r23, __tmp_reg__
  2645. DEFUN __popcountdi2
  2646. XCALL __popcountsi2
  2647. push r24
  2648. mov_l r22, r18
  2649. mov_h r23, r19
  2650. mov_l r24, r20
  2651. mov_h r25, r21
  2652. XCALL __popcountsi2
  2653. XJMP __popcounthi2_tail
  2654. ENDF __popcountdi2
  2655. #endif /* defined (L_popcountdi2) */
  2656. #if defined (L_popcountqi2)
  2657. ;; population count
  2658. ;; r24 = popcount8 (r24)
  2659. ;; clobbers: __tmp_reg__
  2660. DEFUN __popcountqi2
  2661. mov __tmp_reg__, r24
  2662. andi r24, 1
  2663. lsr __tmp_reg__
  2664. lsr __tmp_reg__
  2665. adc r24, __zero_reg__
  2666. lsr __tmp_reg__
  2667. adc r24, __zero_reg__
  2668. lsr __tmp_reg__
  2669. adc r24, __zero_reg__
  2670. lsr __tmp_reg__
  2671. adc r24, __zero_reg__
  2672. lsr __tmp_reg__
  2673. adc r24, __zero_reg__
  2674. lsr __tmp_reg__
  2675. adc r24, __tmp_reg__
  2676. ret
  2677. ENDF __popcountqi2
  2678. #endif /* defined (L_popcountqi2) */
  2679. /**********************************
  2680. * Swap bytes
  2681. **********************************/
  2682. ;; swap two registers with different register number
  2683. .macro bswap a, b
  2684. eor \a, \b
  2685. eor \b, \a
  2686. eor \a, \b
  2687. .endm
  2688. #if defined (L_bswapsi2)
  2689. ;; swap bytes
  2690. ;; r25:r22 = bswap32 (r25:r22)
  2691. DEFUN __bswapsi2
  2692. bswap r22, r25
  2693. bswap r23, r24
  2694. ret
  2695. ENDF __bswapsi2
  2696. #endif /* defined (L_bswapsi2) */
  2697. #if defined (L_bswapdi2)
  2698. ;; swap bytes
  2699. ;; r25:r18 = bswap64 (r25:r18)
  2700. DEFUN __bswapdi2
  2701. bswap r18, r25
  2702. bswap r19, r24
  2703. bswap r20, r23
  2704. bswap r21, r22
  2705. ret
  2706. ENDF __bswapdi2
  2707. #endif /* defined (L_bswapdi2) */
  2708. /**********************************
  2709. * 64-bit shifts
  2710. **********************************/
  2711. #if defined (L_ashrdi3)
  2712. #define SS __zero_reg__
  2713. ;; Arithmetic shift right
  2714. ;; r25:r18 = ashr64 (r25:r18, r17:r16)
  2715. DEFUN __ashrdi3
  2716. sbrc r25, 7
  2717. com SS
  2718. ;; FALLTHRU
  2719. ENDF __ashrdi3
  2720. ;; Logic shift right
  2721. ;; r25:r18 = lshr64 (r25:r18, r17:r16)
  2722. DEFUN __lshrdi3
  2723. ;; Signs are in SS (zero_reg)
  2724. mov __tmp_reg__, r16
  2725. 0: cpi r16, 8
  2726. brlo 2f
  2727. subi r16, 8
  2728. mov r18, r19
  2729. mov r19, r20
  2730. mov r20, r21
  2731. mov r21, r22
  2732. mov r22, r23
  2733. mov r23, r24
  2734. mov r24, r25
  2735. mov r25, SS
  2736. rjmp 0b
  2737. 1: asr SS
  2738. ror r25
  2739. ror r24
  2740. ror r23
  2741. ror r22
  2742. ror r21
  2743. ror r20
  2744. ror r19
  2745. ror r18
  2746. 2: dec r16
  2747. brpl 1b
  2748. clr __zero_reg__
  2749. mov r16, __tmp_reg__
  2750. ret
  2751. ENDF __lshrdi3
  2752. #undef SS
  2753. #endif /* defined (L_ashrdi3) */
  2754. #if defined (L_ashldi3)
  2755. ;; Shift left
  2756. ;; r25:r18 = ashl64 (r25:r18, r17:r16)
  2757. ;; This function does not clobber T.
  2758. DEFUN __ashldi3
  2759. mov __tmp_reg__, r16
  2760. 0: cpi r16, 8
  2761. brlo 2f
  2762. mov r25, r24
  2763. mov r24, r23
  2764. mov r23, r22
  2765. mov r22, r21
  2766. mov r21, r20
  2767. mov r20, r19
  2768. mov r19, r18
  2769. clr r18
  2770. subi r16, 8
  2771. rjmp 0b
  2772. 1: lsl r18
  2773. rol r19
  2774. rol r20
  2775. rol r21
  2776. rol r22
  2777. rol r23
  2778. rol r24
  2779. rol r25
  2780. 2: dec r16
  2781. brpl 1b
  2782. mov r16, __tmp_reg__
  2783. ret
  2784. ENDF __ashldi3
  2785. #endif /* defined (L_ashldi3) */
  2786. #if defined (L_rotldi3)
  2787. ;; Rotate left
  2788. ;; r25:r18 = rotl64 (r25:r18, r17:r16)
  2789. DEFUN __rotldi3
  2790. push r16
  2791. 0: cpi r16, 8
  2792. brlo 2f
  2793. subi r16, 8
  2794. mov __tmp_reg__, r25
  2795. mov r25, r24
  2796. mov r24, r23
  2797. mov r23, r22
  2798. mov r22, r21
  2799. mov r21, r20
  2800. mov r20, r19
  2801. mov r19, r18
  2802. mov r18, __tmp_reg__
  2803. rjmp 0b
  2804. 1: lsl r18
  2805. rol r19
  2806. rol r20
  2807. rol r21
  2808. rol r22
  2809. rol r23
  2810. rol r24
  2811. rol r25
  2812. adc r18, __zero_reg__
  2813. 2: dec r16
  2814. brpl 1b
  2815. pop r16
  2816. ret
  2817. ENDF __rotldi3
  2818. #endif /* defined (L_rotldi3) */
  2819. .section .text.libgcc.fmul, "ax", @progbits
  2820. /***********************************************************/
  2821. ;;; Softmul versions of FMUL, FMULS and FMULSU to implement
  2822. ;;; __builtin_avr_fmul* if !AVR_HAVE_MUL
  2823. /***********************************************************/
  2824. #define A1 24
  2825. #define B1 25
  2826. #define C0 22
  2827. #define C1 23
  2828. #define A0 __tmp_reg__
  2829. #ifdef L_fmuls
  2830. ;;; r23:r22 = fmuls (r24, r25) like in FMULS instruction
  2831. ;;; Clobbers: r24, r25, __tmp_reg__
  2832. DEFUN __fmuls
  2833. ;; A0.7 = negate result?
  2834. mov A0, A1
  2835. eor A0, B1
  2836. ;; B1 = |B1|
  2837. sbrc B1, 7
  2838. neg B1
  2839. XJMP __fmulsu_exit
  2840. ENDF __fmuls
  2841. #endif /* L_fmuls */
  2842. #ifdef L_fmulsu
  2843. ;;; r23:r22 = fmulsu (r24, r25) like in FMULSU instruction
  2844. ;;; Clobbers: r24, r25, __tmp_reg__
  2845. DEFUN __fmulsu
  2846. ;; A0.7 = negate result?
  2847. mov A0, A1
  2848. ;; FALLTHRU
  2849. ENDF __fmulsu
  2850. ;; Helper for __fmuls and __fmulsu
  2851. DEFUN __fmulsu_exit
  2852. ;; A1 = |A1|
  2853. sbrc A1, 7
  2854. neg A1
  2855. #ifdef __AVR_ERRATA_SKIP_JMP_CALL__
  2856. ;; Some cores have problem skipping 2-word instruction
  2857. tst A0
  2858. brmi 1f
  2859. #else
  2860. sbrs A0, 7
  2861. #endif /* __AVR_HAVE_JMP_CALL__ */
  2862. XJMP __fmul
  2863. 1: XCALL __fmul
  2864. ;; C = -C iff A0.7 = 1
  2865. NEG2 C0
  2866. ret
  2867. ENDF __fmulsu_exit
  2868. #endif /* L_fmulsu */
  2869. #ifdef L_fmul
  2870. ;;; r22:r23 = fmul (r24, r25) like in FMUL instruction
  2871. ;;; Clobbers: r24, r25, __tmp_reg__
  2872. DEFUN __fmul
  2873. ; clear result
  2874. clr C0
  2875. clr C1
  2876. clr A0
  2877. 1: tst B1
  2878. ;; 1.0 = 0x80, so test for bit 7 of B to see if A must to be added to C.
  2879. 2: brpl 3f
  2880. ;; C += A
  2881. add C0, A0
  2882. adc C1, A1
  2883. 3: ;; A >>= 1
  2884. lsr A1
  2885. ror A0
  2886. ;; B <<= 1
  2887. lsl B1
  2888. brne 2b
  2889. ret
  2890. ENDF __fmul
  2891. #endif /* L_fmul */
  2892. #undef A0
  2893. #undef A1
  2894. #undef B1
  2895. #undef C0
  2896. #undef C1
  2897. #include "lib1funcs-fixed.S"