2
0

lbn68000.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. /*
  2. * Copyright (c) 1995 Colin Plumb. All rights reserved.
  3. * For licensing and other legal details, see the file legal.c.
  4. *
  5. * lbn68000.c - 16-bit bignum primitives for the 68000 (or 68010) processors.
  6. *
  7. * This was written for Metrowerks C, and while it should be reasonably
  8. * portable, NOTE that Metrowerks lets a callee trash a0, a1, d0, d1, and d2.
  9. * Some 680x0 compilers make d2 callee-save, so instructions to save it
  10. * will have to be added.
  11. *
  12. * This code supports 16 or 32-bit ints, based on UINT_MAX.
  13. * Regardless of UINT_MAX, only bignums up to 64K words (1 million bits)
  14. * are supported. (68k hackers will recognize this as a consequence of
  15. * using dbra.)
  16. *
  17. * These primitives use little-endian word order.
  18. * (The order of bytes within words is irrelevant to this issue.)
  19. */
  20. #include <limits.h>
  21. #include "lbn.h" /* Should include lbn68000.h */
  22. /*
  23. * The Metrowerks C compiler (1.2.2) produces bad 68k code for the
  24. * following input, which happens to be the inner loop of lbnSub1,
  25. * so a few less than critical routines have been recoded in assembly
  26. * to avoid the bug. (Optimizer on or off does not matter.)
  27. *
  28. * unsigned
  29. * decrement(unsigned *num, unsigned len)
  30. * {
  31. * do {
  32. * if ((*num++)-- != 0)
  33. * return 0;
  34. * } while (--len);
  35. * return 1;
  36. * }
  37. */
  38. asm BNWORD16
  39. lbnSub1_16(BNWORD16 *num, unsigned len, BNWORD16 borrow)
  40. {
  41. movea.l 4(sp),a0 /* num */
  42. #if UINT_MAX == 0xffff
  43. move.w 10(sp),d0 /* borrow */
  44. #else
  45. move.w 12(sp),d0 /* borrow */
  46. #endif
  47. sub.w d0,(a0)+
  48. bcc done
  49. #if UINT_MAX == 0xffff
  50. move.w 8(sp),d0 /* len */
  51. #else
  52. move.w 10(sp),d0 /* len */
  53. #endif
  54. subq.w #2,d0
  55. bcs done
  56. loop:
  57. subq.w #1,(a0)+
  58. dbcc d0,loop
  59. done:
  60. moveq.l #0,d0
  61. addx.w d0,d0
  62. rts
  63. }
  64. asm BNWORD16
  65. lbnAdd1_16(BNWORD16 *num, unsigned len, BNWORD16 carry)
  66. {
  67. movea.l 4(sp),a0 /* num */
  68. #if UINT_MAX == 0xffff
  69. move.w 10(sp),d0 /* carry */
  70. #else
  71. move.w 12(sp),d0 /* carry */
  72. #endif
  73. add.w d0,(a0)+
  74. bcc done
  75. #if UINT_MAX == 0xffff
  76. move.w 8(sp),d0 /* len */
  77. #else
  78. move.w 10(sp),d0 /* len */
  79. #endif
  80. subq.w #2,d0
  81. bcs done
  82. loop:
  83. addq.w #1,(a0)+
  84. dbcc d0,loop
  85. done:
  86. moveq.l #0,d0
  87. addx.w d0,d0
  88. rts
  89. }
  90. asm void
  91. lbnMulN1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k)
  92. {
  93. move.w d3,-(sp) /* 2 bytes of stack frame */
  94. move.l 2+4(sp),a1 /* out */
  95. move.l 2+8(sp),a0 /* in */
  96. #if UINT_MAX == 0xffff
  97. move.w 2+12(sp),d3 /* len */
  98. move.w 2+14(sp),d2 /* k */
  99. #else
  100. move.w 2+14(sp),d3 /* len (low 16 bits) */
  101. move.w 2+16(sp),d2 /* k */
  102. #endif
  103. move.w (a0)+,d1 /* First multiply */
  104. mulu.w d2,d1
  105. move.w d1,(a1)+
  106. clr.w d1
  107. swap d1
  108. subq.w #1,d3 /* Setup for loop unrolling */
  109. lsr.w #1,d3
  110. bcs.s m16_even
  111. beq.s m16_short
  112. subq.w #1,d3 /* Set up software pipeline properly */
  113. move.l d1,d0
  114. m16_loop:
  115. move.w (a0)+,d1
  116. mulu.w d2,d1
  117. add.l d0,d1
  118. move.w d1,(a1)+
  119. clr.w d1
  120. swap d1
  121. m16_even:
  122. move.w (a0)+,d0
  123. mulu.w d2,d0
  124. add.l d1,d0
  125. move.w d0,(a1)+
  126. clr.w d0
  127. swap d0
  128. dbra d3,m16_loop
  129. move.w d0,(a1)
  130. move.w (sp)+,d3
  131. rts
  132. m16_short:
  133. move.w d1,(a1)
  134. move.w (sp)+,d3
  135. rts
  136. }
  137. asm BNWORD16
  138. lbnMulAdd1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k)
  139. {
  140. move.w d4,-(sp)
  141. clr.w d4
  142. move.w d3,-(sp) /* 4 bytes of stack frame */
  143. move.l 4+4(sp),a1 /* out */
  144. move.l 4+8(sp),a0 /* in */
  145. #if UINT_MAX == 0xffff
  146. move.w 4+12(sp),d3 /* len */
  147. move.w 4+14(sp),d2 /* k */
  148. #else
  149. move.w 4+14(sp),d3 /* len (low 16 bits) */
  150. move.w 4+16(sp),d2 /* k */
  151. #endif
  152. move.w (a0)+,d1 /* First multiply */
  153. mulu.w d2,d1
  154. add.w d1,(a1)+
  155. clr.w d1
  156. swap d1
  157. addx.w d4,d1
  158. subq.w #1,d3 /* Setup for loop unrolling */
  159. lsr.w #1,d3
  160. bcs.s ma16_even
  161. beq.s ma16_short
  162. subq.w #1,d3 /* Set up software pipeline properly */
  163. move.l d1,d0
  164. ma16_loop:
  165. move.w (a0)+,d1
  166. mulu.w d2,d1
  167. add.l d0,d1
  168. add.w d1,(a1)+
  169. clr.w d1
  170. swap d1
  171. addx.w d4,d1
  172. ma16_even:
  173. move.w (a0)+,d0
  174. mulu.w d2,d0
  175. add.l d1,d0
  176. add.w d0,(a1)+
  177. clr.w d0
  178. swap d0
  179. addx.w d4,d0
  180. dbra d3,ma16_loop
  181. move.w (sp)+,d3
  182. move.w (sp)+,d4
  183. rts
  184. ma16_short:
  185. move.w (sp)+,d3
  186. move.l d1,d0
  187. move.w (sp)+,d4
  188. rts
  189. }
  190. asm BNWORD16
  191. lbnMulSub1_16(BNWORD16 *out, BNWORD16 const *in, unsigned len, BNWORD16 k)
  192. {
  193. move.w d4,-(sp)
  194. clr.w d4
  195. move.w d3,-(sp) /* 4 bytes of stack frame */
  196. move.l 4+4(sp),a1 /* out */
  197. move.l 4+8(sp),a0 /* in */
  198. #if UINT_MAX == 0xffff
  199. move.w 4+12(sp),d3 /* len */
  200. move.w 4+14(sp),d2 /* k */
  201. #else
  202. move.w 4+14(sp),d3 /* len (low 16 bits) */
  203. move.w 4+16(sp),d2 /* k */
  204. #endif
  205. move.w (a0)+,d1 /* First multiply */
  206. mulu.w d2,d1
  207. sub.w d1,(a1)+
  208. clr.w d1
  209. swap d1
  210. addx.w d4,d1
  211. subq.w #1,d3 /* Setup for loop unrolling */
  212. lsr.w #1,d3
  213. bcs.s ms16_even
  214. beq.s ms16_short
  215. subq.w #1,d3 /* Set up software pipeline properly */
  216. move.l d1,d0
  217. ms16_loop:
  218. move.w (a0)+,d1
  219. mulu.w d2,d1
  220. add.l d0,d1
  221. sub.w d1,(a1)+
  222. clr.w d1
  223. swap d1
  224. addx.w d4,d1
  225. ms16_even:
  226. move.w (a0)+,d0
  227. mulu.w d2,d0
  228. add.l d1,d0
  229. sub.w d0,(a1)+
  230. clr.w d0
  231. swap d0
  232. addx.w d4,d0
  233. dbra d3,ms16_loop
  234. move.w (sp)+,d3
  235. move.w (sp)+,d4
  236. rts
  237. ms16_short:
  238. move.w (sp)+,d3
  239. move.l d1,d0
  240. move.w (sp)+,d4
  241. rts
  242. }
  243. /* The generic long/short divide doesn't know that nh < d */
  244. asm BNWORD16
  245. lbnDiv21_16(BNWORD16 *q, BNWORD16 nh, BNWORD16 nl, BNWORD16 d)
  246. {
  247. move.l 8(sp),d0 /* nh *and* nl */
  248. divu.w 12(sp),d0
  249. move.l 4(sp),a0
  250. move.w d0,(a0)
  251. clr.w d0
  252. swap d0
  253. rts
  254. }
  255. asm unsigned
  256. lbnModQ_16(BNWORD16 const *n, unsigned len, BNWORD16 d)
  257. {
  258. move.l 4(sp),a0 /* n */
  259. moveq.l #0,d1
  260. #if UINT_MAX == 0xffff
  261. move.w 8(sp),d1 /* len */
  262. move.w 10(sp),d2 /* d */
  263. #else
  264. move.w 10(sp),d1 /* len (low 16 bits) */
  265. move.w 12(sp),d2 /* d */
  266. #endif
  267. add.l d1,a0
  268. add.l d1,a0 /* n += len */
  269. moveq.l #0,d0
  270. subq.w #1,d1
  271. mq16_loop:
  272. move.w -(a0),d0 /* Assemble remainder and new word */
  273. divu.w d2,d0 /* Put remainder in high half of d0 */
  274. dbra d1,mq16_loop
  275. mq16_done:
  276. clr.w d0
  277. swap d0
  278. rts
  279. }
  280. /*
  281. * Detect if this is a 32-bit processor (68020+ *or* CPU32).
  282. * Both the 68020+ and CPU32 processors (which have 32x32->64-bit
  283. * multiply, what the 32-bit math library wants) support scaled indexed
  284. * addressing. The 68000 and 68010 ignore the scale selection
  285. * bits, treating it as *1 all the time. So a 32-bit processor
  286. * will evaluate -2(a0,a0.w*2) as 1+1*2-2 = 1.
  287. * A 16-bit processor will compute 1+1-2 = 0.
  288. *
  289. * Thus, the return value will indicate whether the chip this is
  290. * running on supports 32x32->64-bit multiply (mulu.l).
  291. */
  292. asm int
  293. is68020(void)
  294. {
  295. machine 68020
  296. lea 1,a0
  297. #if 0
  298. lea -2(a0,a0.w*2),a0 /* Metrowerks won't assemble this, arrgh */
  299. #else
  300. dc.w 0x41f0, 0x82fe
  301. #endif
  302. move.l a0,d0
  303. rts
  304. }
  305. /*
  306. * Since I had to hand-assemble that fancy addressing mode, I had to study
  307. * up on 680x0 addressing modes.
  308. * A summary of 680x0 addressing modes.
  309. * A 68000 effective address specifies an operand on an instruction, which
  310. * may be a register or in memory. It is made up of a 3-bit mode and a
  311. * 3-bit register specifier. The meanings of the various modes are:
  312. *
  313. * 000 reg - Dn, n specified by "reg"
  314. * 001 reg - An, n specified by "reg"
  315. * 010 reg - (An)
  316. * 011 reg - (An)+
  317. * 100 reg - -(An)
  318. * 101 reg - d16(An), one 16-bit displacement word follows, sign-extended
  319. * 110 reg - Fancy addressing mode off of An, see extension word below
  320. * 111 000 - abs.W, one 16-bit signed absolute address follows
  321. * 111 001 - abs.L, one 32-bit absolute address follows
  322. * 111 010 - d16(PC), one 16-bit displacemnt word follows, sign-extended
  323. * 111 011 - Fancy addressing mode off of PC, see extension word below
  324. * 111 100 - #immediate, followed by 16 or 32 bits of immediate value
  325. * 111 101 - unused, reserved
  326. * 111 110 - unused, reserved
  327. * 111 111 - unused, reserved
  328. *
  329. * Memory references are to data space, except that PC-relative references
  330. * are to program space, and are read-only.
  331. *
  332. * Fancy addressing modes are followed by a 16-bit extension word, and come
  333. * in "brief" and "full" forms.
  334. * The "brief" form looks like this. Bit 8 is 0 to indicate this form:
  335. *
  336. * 1 1 1 1 1 1 1
  337. * 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
  338. * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
  339. * |A/D| register |L/W| scale | 0 | 8-bit signed displacement |
  340. * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
  341. *
  342. * The basic effective address specifies a 32-bit base register - A0 through
  343. * A7 or PC (the address of the following instruction).
  344. * The A/D and register fields specify an index register. A/D is 1 for
  345. * address registers, and 0 for data registers. L/W specifies the length
  346. * of the index register, 1 for 32 bits, and 0 for 16 bits (sign-extended).
  347. * The scale field is a left shift amount (0 to 3 bits) to apply to the
  348. * sign-extended index register. The final address is d8(An,Rn.X*SCALE),
  349. * also written (d8,An,Rn.X*SCALE). X is "W" or "L", SCALE is 1, 2, 4 or 8.
  350. * "*1" may be omitted, as may a d8 of 0.
  351. *
  352. * The 68000 supports this form, but only with a scale field of 0.
  353. * It does NOT (says the MC68030 User's Manual MC68030UM/AD, section 2.7)
  354. * decode the scale field and the following format bit. They are treated
  355. * as 0.
  356. * I recall (I don't have the data book handy) that the CPU32 processor
  357. * core used in the 683xx series processors supports variable scales,
  358. * but only the brief extension word form. I suspect it decodes the
  359. * format bit and traps if it is not zero, but I don't recall.
  360. *
  361. * The "full" form (680x0, x >= 2 processors only) looks like this:
  362. *
  363. * 1 1 1 1 1 1 1
  364. * 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
  365. * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
  366. * |A/D| register |L/W| scale | 1 | BS| IS|BD size| 0 | P |OD size|
  367. * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
  368. *
  369. * The first 8 bits are interpreted the same way as in the brief form,
  370. * except that bit 8 is set to 1 to indicate the full form.
  371. * BS, Base Suppress, if set, causes a value of 0 to be used in place of
  372. * the base register value. If this is set, the base register
  373. * specified is irrelevant, except that if it is the PC, the fetch is
  374. * still done from program space. The specifier "ZPC" can be used in
  375. * place of "PC" in the effective address mnemonic to represent this
  376. * case.
  377. * IS, Index Suppress, if set, causes a value of 0 to be used in place
  378. * of the scaled index register. In this case, the first 7 bits of the
  379. * extension word are irrelevant.
  380. * BD size specifies the base displacement size. A value of 00
  381. * in this field is illegal, while 01, 10 and 11 indicate that the
  382. * extension word is followed by 0, 1 or 2 16-bit words of base displacement
  383. * (zero, sign-extended to 32 bits, and most-significant word first,
  384. * respectively) to add to the base register value.
  385. * Bit 3 is unused.
  386. * The P bit is the pre/post indexing bit, and only applies if an outer
  387. * displacement is used. This is explained later.
  388. * OD size specifies the size of an outer displacement. In the simple
  389. * case, this field is set to 00 and the effective address is
  390. * (disp,An,Rn.X*SCALE) or (disp,PC,Rn.X*SCALE).
  391. * In this case the P bit must be 0. Any of those compnents may be
  392. * suppressed, with a BD size of 01, the BS bit, or the IS bit.
  393. * If the OD size is not 00, it encodes an outer displacement in the same
  394. * manner as the BD size, and 0, 1 or 2 16-bit words of outer displacement
  395. * follow the base displacement in the instruction stream. In this case,
  396. * this is a double-indirect addressing mode. The base, base displacement,
  397. * and possibly the index, specify a 32-bit memory word which holds a value
  398. * which is fetched, and the outer displacement and possibly the index are
  399. * added to produce the address of the operand.
  400. * If the P bit is 0, this is pre-indexed, and the index value is added
  401. * before the fetch of the indirect word, producing an effective address
  402. * of ([disp,An,Rn.X*SCALE],disp). If the P bit is 1, the post-indexed case,
  403. * the memory word is fectched from base+base displacement, then the index
  404. * and outer displacement are added to compute the address of the operand.
  405. * This effective address is written ([disp,An],Rn.X*SCALE,disp).
  406. * (In both cases, "An" may also be "PC" or "ZPC".)
  407. * Any of the components may be omitted. If the index is omitted (using the
  408. * IS bit), the P bit is irrelevant, but must be written as 0.
  409. * Thus, legal combinations of IS, P and OD size are:
  410. * 0 0 00 - (disp,An,Rn.X*SCALE), also written disp(An,Rn.X*SCALE)
  411. * 0 0 01 - ([disp,An,Rn.X*SCALE])
  412. * 0 0 10 - ([disp,An,Rn.X*SCALE],d16)
  413. * 0 0 11 - ([disp,An,Rn.X*SCALE],d32)
  414. * 0 1 01 - ([disp,An],Rn.X*SCALE)
  415. * 0 1 10 - ([disp,An],Rn.X*SCALE,d16)
  416. * 0 1 11 - ([disp,An],Rn.X*SCALE,d32)
  417. * 1 0 00 - (disp,An), also written disp(An)
  418. * 1 0 01 - ([disp,An])
  419. * 1 0 10 - ([disp,An],d16)
  420. * 1 0 11 - ([disp,An],d32)
  421. */
  422. /* 45678901234567890123456789012345678901234567890123456789012345678901234567 */