123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434 |
- /*
- * Sources of the "INTEGER ARITHMETIC" group instructions
- */
- /* $Header$ */
- #include <em_abs.h>
- #include "logging.h"
- #include "global.h"
- #include "log.h"
- #include "mem.h"
- #include "trap.h"
- #include "warn.h"
- #include "text.h"
- #include "fra.h"
- PRIVATE long adi(), sbi(), dvi(), mli(), rmi(), ngi(), sli(), sri();
- DoADIl2(arg)
- size arg;
- {
- /* ADI w: Addition (*) */
- register size l = (L_arg_2() * arg);
- register long t = spop(arg_wi(l));
- LOG(("@I6 DoADIl2(%ld)", l));
- spoilFRA();
- npush(adi(spop(l), t, l), l);
- }
- DoADIm(arg)
- size arg;
- {
- /* ADI w: Addition (*) */
- register size l = arg_wi(arg);
- register long t = spop(l);
- LOG(("@I6 DoADIm(%ld)", l));
- spoilFRA();
- npush(adi(spop(l), t, l), l);
- }
- DoADIz() /* argument on top of stack */
- {
- /* ADI w: Addition (*) */
- register size l = upop(wsize);
- register long t = spop(arg_wi(l));
- LOG(("@I6 DoADIz(%ld)", l));
- spoilFRA();
- npush(adi(spop(l), t, l), l);
- }
- DoSBIl2(arg)
- size arg;
- {
- /* SBI w: Subtraction (*) */
- register size l = (L_arg_2() * arg);
- register long t = spop(arg_wi(l));
- LOG(("@I6 DoSBIl2(%ld)", l));
- spoilFRA();
- npush(sbi(spop(l), t, l), l);
- }
- DoSBIm(arg)
- size arg;
- {
- /* SBI w: Subtraction (*) */
- register size l = arg_wi(arg);
- register long t = spop(l);
- LOG(("@I6 DoSBIm(%ld)", l));
- spoilFRA();
- npush(sbi(spop(l), t, l), l);
- }
- DoSBIz() /* arg on top of stack */
- {
- /* SBI w: Subtraction (*) */
- register size l = upop(wsize);
- register long t = spop(arg_wi(l));
- LOG(("@I6 DoSBIz(%ld)", l));
- spoilFRA();
- npush(sbi(spop(l), t, l), l);
- }
- DoMLIl2(arg)
- size arg;
- {
- /* MLI w: Multiplication (*) */
- register size l = (L_arg_2() * arg);
- register long t = spop(arg_wi(l));
- LOG(("@I6 DoMLIl2(%ld)", l));
- spoilFRA();
- npush(mli(spop(l), t, l), l);
- }
- DoMLIm(arg)
- size arg;
- {
- /* MLI w: Multiplication (*) */
- register size l = arg_wi(arg);
- register long t = spop(l);
- LOG(("@I6 DoMLIm(%ld)", l));
- spoilFRA();
- npush(mli(spop(l), t, l), l);
- }
- DoMLIz() /* arg on top of stack */
- {
- /* MLI w: Multiplication (*) */
- register size l = upop(wsize);
- register long t = spop(arg_wi(l));
- LOG(("@I6 DoMLIz(%ld)", l));
- spoilFRA();
- npush(mli(spop(l), t, l), l);
- }
- DoDVIl2(arg)
- size arg;
- {
- /* DVI w: Division (*) */
- register size l = (L_arg_2() * arg);
- register long t = spop(arg_wi(l));
- LOG(("@I6 DoDVIl2(%ld)", l));
- spoilFRA();
- npush(dvi(spop(l), t), l);
- }
- DoDVIm(arg)
- size arg;
- {
- /* DVI w: Division (*) */
- register size l = arg_wi(arg);
- register long t = spop(l);
- LOG(("@I6 DoDVIm(%ld)", l));
- spoilFRA();
- npush(dvi(spop(l), t), l);
- }
- DoDVIz() /* arg on top of stack */
- {
- /* DVI w: Division (*) */
- register size l = upop(wsize);
- register long t = spop(arg_wi(l));
- LOG(("@I6 DoDVIz(%ld)", l));
- spoilFRA();
- npush(dvi(spop(l), t), l);
- }
- DoRMIl2(arg)
- size arg;
- {
- /* RMI w: Remainder (*) */
- register size l = (L_arg_2() * arg);
- register long t = spop(arg_wi(l));
- LOG(("@I6 DoRMIl2(%ld)", l));
- spoilFRA();
- npush(rmi(spop(l), t), l);
- }
- DoRMIm(arg)
- size arg;
- {
- /* RMI w: Remainder (*) */
- register size l = arg_wi(arg);
- register long t = spop(l);
- LOG(("@I6 DoRMIm(%ld)", l));
- spoilFRA();
- npush(rmi(spop(l), t), l);
- }
- DoRMIz() /* arg on top of stack */
- {
- /* RMI w: Remainder (*) */
- register size l = upop(wsize);
- register long t = spop(arg_wi(l));
- LOG(("@I6 DoRMIz(%ld)", l));
- spoilFRA();
- npush(rmi(spop(l), t), l);
- }
- DoNGIl2(arg)
- size arg;
- {
- /* NGI w: Negate (two's complement) (*) */
- register size l = (L_arg_2() * arg);
- LOG(("@I6 DoNGIl2(%ld)", l));
- spoilFRA();
- l = arg_wi(l);
- npush(ngi(spop(l), l), l);
- }
- DoNGIz()
- {
- /* NGI w: Negate (two's complement) (*) */
- register size l = upop(wsize);
- LOG(("@I6 DoNGIz(%ld)", l));
- spoilFRA();
- l = arg_wi(l);
- npush(ngi(spop(l), l), l);
- }
- DoSLIl2(arg)
- size arg;
- {
- /* SLI w: Shift left (*) */
- register size l = (L_arg_2() * arg);
- register long t = spop(wsize);
- LOG(("@I6 DoSLIl2(%ld)", l));
- spoilFRA();
- l = arg_wi(l);
- npush(sli(spop(l), t, l), l);
- }
- DoSLIm(arg)
- size arg;
- {
- /* SLI w: Shift left (*) */
- register size l = arg_wi(arg);
- register long t = spop(wsize);
- LOG(("@I6 DoSLIm(%ld)", l));
- spoilFRA();
- npush(sli(spop(l), t, l), l);
- }
- DoSLIz()
- {
- /* SLI w: Shift left (*) */
- register size l = upop(wsize);
- register long t = spop(wsize);
- LOG(("@I6 DoSLIz(%ld)", l));
- spoilFRA();
- l = arg_wi(l);
- npush(sli(spop(l), t, l), l);
- }
- DoSRIl2(arg)
- size arg;
- {
- /* SRI w: Shift right (*) */
- register size l = (L_arg_2() * arg);
- register long t = spop(wsize);
- LOG(("@I6 DoSRIl2(%ld)", l));
- spoilFRA();
- l = arg_wi(l);
- npush(sri(spop(l), t, l), l);
- }
- DoSRIz()
- {
- /* SRI w: Shift right (*) */
- register size l = upop(wsize);
- register long t = spop(wsize);
- LOG(("@I6 DoSRIz(%ld)", l));
- spoilFRA();
- l = arg_wi(l);
- npush(sri(spop(l), t, l), l);
- }
- #define i_maxs(n) ((n == 2) ? I_MAXS2 : I_MAXS4)
- #define i_mins(n) ((n == 2) ? I_MINS2 : I_MINS4)
- PRIVATE long adi(w1, w2, nbytes) /* returns w1 + w2 */
- long w1, w2;
- size nbytes;
- {
- if (must_test && !(IgnMask&BIT(EIOVFL))) {
- if (w1 > 0 && w2 > 0) {
- if (i_maxs(nbytes) - w1 < w2)
- trap(EIOVFL);
- }
- else if (w1 < 0 && w2 < 0) {
- if (i_mins(nbytes) - w1 > w2)
- trap(EIOVFL);
- }
- }
- return (w1 + w2);
- }
- PRIVATE long sbi(w1, w2, nbytes) /* returns w1 - w2 */
- long w1, w2;
- size nbytes;
- {
- if (must_test && !(IgnMask&BIT(EIOVFL))) {
- if (w2 < 0 && w1 > 0) {
- if (i_maxs(nbytes) + w2 < w1)
- trap(EIOVFL);
- }
- else if (w2 > 0 && w1 < 0) {
- if (i_mins(nbytes) + w2 > w1) {
- trap(EIOVFL);
- }
- }
- }
- return (w1 - w2);
- }
- #define labs(w) ((w < 0) ? (-w) : w)
- PRIVATE long mli(w1, w2, nbytes) /* returns w1 * w2 */
- long w1, w2;
- size nbytes;
- {
- if (w1 == 0 || w2 == 0)
- return (0L);
- if (must_test && !(IgnMask&BIT(EIOVFL))) {
- if ((w1 > 0 && w2 > 0) || (w2 < 0 && w1 < 0)) {
- if ( w1 == i_mins(nbytes) || w2 == i_mins(nbytes)
- || (i_maxs(nbytes) / labs(w1)) < labs(w2)
- ) {
- trap(EIOVFL);
- }
- }
- else if (w1 > 0) {
- if (i_mins(nbytes) / w1 > w2)
- trap(EIOVFL);
- }
- else if (i_mins(nbytes) / w2 > w1) {
- trap(EIOVFL);
- }
- }
- return (w1 * w2);
- }
- PRIVATE long dvi(w1, w2)
- long w1, w2;
- {
- if (w2 == 0) {
- if (!(IgnMask&BIT(EIDIVZ))) {
- trap(EIDIVZ);
- }
- else return (0L);
- }
- return (w1 / w2);
- }
- PRIVATE long rmi(w1, w2)
- long w1, w2;
- {
- if (w2 == 0) {
- if (!(IgnMask&BIT(EIDIVZ))) {
- trap(EIDIVZ);
- }
- else return (0L);
- }
- return (w1 % w2);
- }
- PRIVATE long ngi(w1, nbytes)
- long w1;
- size nbytes;
- {
- if (must_test && !(IgnMask&BIT(EIOVFL))) {
- if (w1 == i_mins(nbytes)) {
- trap(EIOVFL);
- }
- }
- return (-w1);
- }
- PRIVATE long sli(w1, w2, nbytes) /* w1 << w2 */
- long w1, w2;
- size nbytes;
- {
- if (must_test) {
- #ifdef LOGGING
- /* check shift distance */
- if (w2 < 0) {
- warning(WSHNEG);
- w2 = 0;
- }
- if (w2 >= nbytes*8) {
- warning(WSHLARGE);
- w2 = nbytes*8 - 1;
- }
- #endif LOGGING
-
- if (!(IgnMask&BIT(EIOVFL))) {
- /* check overflow */
- if ( (w1 >= 0 && (w1 >> (nbytes*8 - w2)) != 0)
- || (w1 < 0 && (w1 >> (nbytes*8 - w2)) != -1)
- ) {
- trap(EIOVFL);
- }
- }
- }
- /* calculate result */
- return (w1 << w2);
- }
- /*ARGSUSED*/
- PRIVATE long sri(w1, w2, nbytes) /* w1 >> w2 */
- long w1, w2;
- size nbytes;
- {
- #ifdef LOGGING
- if (must_test) {
- /* check shift distance */
- if (w2 < 0) {
- warning(WSHNEG);
- w2 = 0;
- }
- if (w2 >= nbytes*8) {
- warning(WSHLARGE);
- w2 = nbytes*8 - 1;
- }
- }
- #endif LOGGING
-
- /* calculate result */
- return (w1 >> w2);
- }
|