do_intar.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. /*
  2. * Sources of the "INTEGER ARITHMETIC" group instructions
  3. */
  4. /* $Header$ */
  5. #include <em_abs.h>
  6. #include "logging.h"
  7. #include "global.h"
  8. #include "log.h"
  9. #include "mem.h"
  10. #include "trap.h"
  11. #include "warn.h"
  12. #include "text.h"
  13. #include "fra.h"
  14. PRIVATE long adi(), sbi(), dvi(), mli(), rmi(), ngi(), sli(), sri();
  15. DoADIl2(arg)
  16. size arg;
  17. {
  18. /* ADI w: Addition (*) */
  19. register size l = (L_arg_2() * arg);
  20. register long t = spop(arg_wi(l));
  21. LOG(("@I6 DoADIl2(%ld)", l));
  22. spoilFRA();
  23. npush(adi(spop(l), t, l), l);
  24. }
  25. DoADIm(arg)
  26. size arg;
  27. {
  28. /* ADI w: Addition (*) */
  29. register size l = arg_wi(arg);
  30. register long t = spop(l);
  31. LOG(("@I6 DoADIm(%ld)", l));
  32. spoilFRA();
  33. npush(adi(spop(l), t, l), l);
  34. }
  35. DoADIz() /* argument on top of stack */
  36. {
  37. /* ADI w: Addition (*) */
  38. register size l = upop(wsize);
  39. register long t = spop(arg_wi(l));
  40. LOG(("@I6 DoADIz(%ld)", l));
  41. spoilFRA();
  42. npush(adi(spop(l), t, l), l);
  43. }
  44. DoSBIl2(arg)
  45. size arg;
  46. {
  47. /* SBI w: Subtraction (*) */
  48. register size l = (L_arg_2() * arg);
  49. register long t = spop(arg_wi(l));
  50. LOG(("@I6 DoSBIl2(%ld)", l));
  51. spoilFRA();
  52. npush(sbi(spop(l), t, l), l);
  53. }
  54. DoSBIm(arg)
  55. size arg;
  56. {
  57. /* SBI w: Subtraction (*) */
  58. register size l = arg_wi(arg);
  59. register long t = spop(l);
  60. LOG(("@I6 DoSBIm(%ld)", l));
  61. spoilFRA();
  62. npush(sbi(spop(l), t, l), l);
  63. }
  64. DoSBIz() /* arg on top of stack */
  65. {
  66. /* SBI w: Subtraction (*) */
  67. register size l = upop(wsize);
  68. register long t = spop(arg_wi(l));
  69. LOG(("@I6 DoSBIz(%ld)", l));
  70. spoilFRA();
  71. npush(sbi(spop(l), t, l), l);
  72. }
  73. DoMLIl2(arg)
  74. size arg;
  75. {
  76. /* MLI w: Multiplication (*) */
  77. register size l = (L_arg_2() * arg);
  78. register long t = spop(arg_wi(l));
  79. LOG(("@I6 DoMLIl2(%ld)", l));
  80. spoilFRA();
  81. npush(mli(spop(l), t, l), l);
  82. }
  83. DoMLIm(arg)
  84. size arg;
  85. {
  86. /* MLI w: Multiplication (*) */
  87. register size l = arg_wi(arg);
  88. register long t = spop(l);
  89. LOG(("@I6 DoMLIm(%ld)", l));
  90. spoilFRA();
  91. npush(mli(spop(l), t, l), l);
  92. }
  93. DoMLIz() /* arg on top of stack */
  94. {
  95. /* MLI w: Multiplication (*) */
  96. register size l = upop(wsize);
  97. register long t = spop(arg_wi(l));
  98. LOG(("@I6 DoMLIz(%ld)", l));
  99. spoilFRA();
  100. npush(mli(spop(l), t, l), l);
  101. }
  102. DoDVIl2(arg)
  103. size arg;
  104. {
  105. /* DVI w: Division (*) */
  106. register size l = (L_arg_2() * arg);
  107. register long t = spop(arg_wi(l));
  108. LOG(("@I6 DoDVIl2(%ld)", l));
  109. spoilFRA();
  110. npush(dvi(spop(l), t), l);
  111. }
  112. DoDVIm(arg)
  113. size arg;
  114. {
  115. /* DVI w: Division (*) */
  116. register size l = arg_wi(arg);
  117. register long t = spop(l);
  118. LOG(("@I6 DoDVIm(%ld)", l));
  119. spoilFRA();
  120. npush(dvi(spop(l), t), l);
  121. }
  122. DoDVIz() /* arg on top of stack */
  123. {
  124. /* DVI w: Division (*) */
  125. register size l = upop(wsize);
  126. register long t = spop(arg_wi(l));
  127. LOG(("@I6 DoDVIz(%ld)", l));
  128. spoilFRA();
  129. npush(dvi(spop(l), t), l);
  130. }
  131. DoRMIl2(arg)
  132. size arg;
  133. {
  134. /* RMI w: Remainder (*) */
  135. register size l = (L_arg_2() * arg);
  136. register long t = spop(arg_wi(l));
  137. LOG(("@I6 DoRMIl2(%ld)", l));
  138. spoilFRA();
  139. npush(rmi(spop(l), t), l);
  140. }
  141. DoRMIm(arg)
  142. size arg;
  143. {
  144. /* RMI w: Remainder (*) */
  145. register size l = arg_wi(arg);
  146. register long t = spop(l);
  147. LOG(("@I6 DoRMIm(%ld)", l));
  148. spoilFRA();
  149. npush(rmi(spop(l), t), l);
  150. }
  151. DoRMIz() /* arg on top of stack */
  152. {
  153. /* RMI w: Remainder (*) */
  154. register size l = upop(wsize);
  155. register long t = spop(arg_wi(l));
  156. LOG(("@I6 DoRMIz(%ld)", l));
  157. spoilFRA();
  158. npush(rmi(spop(l), t), l);
  159. }
  160. DoNGIl2(arg)
  161. size arg;
  162. {
  163. /* NGI w: Negate (two's complement) (*) */
  164. register size l = (L_arg_2() * arg);
  165. LOG(("@I6 DoNGIl2(%ld)", l));
  166. spoilFRA();
  167. l = arg_wi(l);
  168. npush(ngi(spop(l), l), l);
  169. }
  170. DoNGIz()
  171. {
  172. /* NGI w: Negate (two's complement) (*) */
  173. register size l = upop(wsize);
  174. LOG(("@I6 DoNGIz(%ld)", l));
  175. spoilFRA();
  176. l = arg_wi(l);
  177. npush(ngi(spop(l), l), l);
  178. }
  179. DoSLIl2(arg)
  180. size arg;
  181. {
  182. /* SLI w: Shift left (*) */
  183. register size l = (L_arg_2() * arg);
  184. register long t = spop(wsize);
  185. LOG(("@I6 DoSLIl2(%ld)", l));
  186. spoilFRA();
  187. l = arg_wi(l);
  188. npush(sli(spop(l), t, l), l);
  189. }
  190. DoSLIm(arg)
  191. size arg;
  192. {
  193. /* SLI w: Shift left (*) */
  194. register size l = arg_wi(arg);
  195. register long t = spop(wsize);
  196. LOG(("@I6 DoSLIm(%ld)", l));
  197. spoilFRA();
  198. npush(sli(spop(l), t, l), l);
  199. }
  200. DoSLIz()
  201. {
  202. /* SLI w: Shift left (*) */
  203. register size l = upop(wsize);
  204. register long t = spop(wsize);
  205. LOG(("@I6 DoSLIz(%ld)", l));
  206. spoilFRA();
  207. l = arg_wi(l);
  208. npush(sli(spop(l), t, l), l);
  209. }
  210. DoSRIl2(arg)
  211. size arg;
  212. {
  213. /* SRI w: Shift right (*) */
  214. register size l = (L_arg_2() * arg);
  215. register long t = spop(wsize);
  216. LOG(("@I6 DoSRIl2(%ld)", l));
  217. spoilFRA();
  218. l = arg_wi(l);
  219. npush(sri(spop(l), t, l), l);
  220. }
  221. DoSRIz()
  222. {
  223. /* SRI w: Shift right (*) */
  224. register size l = upop(wsize);
  225. register long t = spop(wsize);
  226. LOG(("@I6 DoSRIz(%ld)", l));
  227. spoilFRA();
  228. l = arg_wi(l);
  229. npush(sri(spop(l), t, l), l);
  230. }
  231. #define i_maxs(n) ((n == 2) ? I_MAXS2 : I_MAXS4)
  232. #define i_mins(n) ((n == 2) ? I_MINS2 : I_MINS4)
  233. PRIVATE long adi(w1, w2, nbytes) /* returns w1 + w2 */
  234. long w1, w2;
  235. size nbytes;
  236. {
  237. if (must_test && !(IgnMask&BIT(EIOVFL))) {
  238. if (w1 > 0 && w2 > 0) {
  239. if (i_maxs(nbytes) - w1 < w2)
  240. trap(EIOVFL);
  241. }
  242. else if (w1 < 0 && w2 < 0) {
  243. if (i_mins(nbytes) - w1 > w2)
  244. trap(EIOVFL);
  245. }
  246. }
  247. return (w1 + w2);
  248. }
  249. PRIVATE long sbi(w1, w2, nbytes) /* returns w1 - w2 */
  250. long w1, w2;
  251. size nbytes;
  252. {
  253. if (must_test && !(IgnMask&BIT(EIOVFL))) {
  254. if (w2 < 0 && w1 > 0) {
  255. if (i_maxs(nbytes) + w2 < w1)
  256. trap(EIOVFL);
  257. }
  258. else if (w2 > 0 && w1 < 0) {
  259. if (i_mins(nbytes) + w2 > w1) {
  260. trap(EIOVFL);
  261. }
  262. }
  263. }
  264. return (w1 - w2);
  265. }
  266. #define labs(w) ((w < 0) ? (-w) : w)
  267. PRIVATE long mli(w1, w2, nbytes) /* returns w1 * w2 */
  268. long w1, w2;
  269. size nbytes;
  270. {
  271. if (w1 == 0 || w2 == 0)
  272. return (0L);
  273. if (must_test && !(IgnMask&BIT(EIOVFL))) {
  274. if ((w1 > 0 && w2 > 0) || (w2 < 0 && w1 < 0)) {
  275. if ( w1 == i_mins(nbytes) || w2 == i_mins(nbytes)
  276. || (i_maxs(nbytes) / labs(w1)) < labs(w2)
  277. ) {
  278. trap(EIOVFL);
  279. }
  280. }
  281. else if (w1 > 0) {
  282. if (i_mins(nbytes) / w1 > w2)
  283. trap(EIOVFL);
  284. }
  285. else if (i_mins(nbytes) / w2 > w1) {
  286. trap(EIOVFL);
  287. }
  288. }
  289. return (w1 * w2);
  290. }
  291. PRIVATE long dvi(w1, w2)
  292. long w1, w2;
  293. {
  294. if (w2 == 0) {
  295. if (!(IgnMask&BIT(EIDIVZ))) {
  296. trap(EIDIVZ);
  297. }
  298. else return (0L);
  299. }
  300. return (w1 / w2);
  301. }
  302. PRIVATE long rmi(w1, w2)
  303. long w1, w2;
  304. {
  305. if (w2 == 0) {
  306. if (!(IgnMask&BIT(EIDIVZ))) {
  307. trap(EIDIVZ);
  308. }
  309. else return (0L);
  310. }
  311. return (w1 % w2);
  312. }
  313. PRIVATE long ngi(w1, nbytes)
  314. long w1;
  315. size nbytes;
  316. {
  317. if (must_test && !(IgnMask&BIT(EIOVFL))) {
  318. if (w1 == i_mins(nbytes)) {
  319. trap(EIOVFL);
  320. }
  321. }
  322. return (-w1);
  323. }
  324. PRIVATE long sli(w1, w2, nbytes) /* w1 << w2 */
  325. long w1, w2;
  326. size nbytes;
  327. {
  328. if (must_test) {
  329. #ifdef LOGGING
  330. /* check shift distance */
  331. if (w2 < 0) {
  332. warning(WSHNEG);
  333. w2 = 0;
  334. }
  335. if (w2 >= nbytes*8) {
  336. warning(WSHLARGE);
  337. w2 = nbytes*8 - 1;
  338. }
  339. #endif LOGGING
  340. if (!(IgnMask&BIT(EIOVFL))) {
  341. /* check overflow */
  342. if ( (w1 >= 0 && (w1 >> (nbytes*8 - w2)) != 0)
  343. || (w1 < 0 && (w1 >> (nbytes*8 - w2)) != -1)
  344. ) {
  345. trap(EIOVFL);
  346. }
  347. }
  348. }
  349. /* calculate result */
  350. return (w1 << w2);
  351. }
  352. /*ARGSUSED*/
  353. PRIVATE long sri(w1, w2, nbytes) /* w1 >> w2 */
  354. long w1, w2;
  355. size nbytes;
  356. {
  357. #ifdef LOGGING
  358. if (must_test) {
  359. /* check shift distance */
  360. if (w2 < 0) {
  361. warning(WSHNEG);
  362. w2 = 0;
  363. }
  364. if (w2 >= nbytes*8) {
  365. warning(WSHLARGE);
  366. w2 = nbytes*8 - 1;
  367. }
  368. }
  369. #endif LOGGING
  370. /* calculate result */
  371. return (w1 >> w2);
  372. }