/* * Sources of the "POINTER ARITHMETIC" group instructions */ /* $Header$ */ #include #include "segcheck.h" #include "global.h" #include "log.h" #include "mem.h" #include "trap.h" #include "warn.h" #include "text.h" #include "fra.h" #define adp(p,w) ((p) + (w)) #define sbs(t,s) ((s) - (t)) #ifdef SEGCHECK #define check_seg(s1,s2,w) if (s1 != s2) { warning(w); } #else #define check_seg(s1,s2,w) #endif SEGCHECK DoADPl2(arg) long arg; { /* ADP f: Add f to pointer on top of stack */ register long l = (L_arg_2() * arg); register ptr p, t = st_lddp(SP); LOG(("@R6 DoADPl2(%ld)", l)); spoilFRA(); if (t == 0) { warning(WNULLPA); } l = arg_f(l); p = adp(t, l); check_seg(ptr2seg(t), ptr2seg(p), WSEGADP); st_stdp(SP, p); } DoADPl4(arg) long arg; { /* ADP f: Add f to pointer on top of stack */ register long l = (L_arg_4() * arg); register ptr p, t = st_lddp(SP); LOG(("@R6 DoADPl4(%ld)", l)); spoilFRA(); if (t == 0) { warning(WNULLPA); } l = arg_f(l); p = adp(t, l); check_seg(ptr2seg(t), ptr2seg(p), WSEGADP); st_stdp(SP, p); } DoADPm(arg) long arg; { /* ADP f: Add f to pointer on top of stack */ register long l = arg_f(arg); register ptr p, t = st_lddp(SP); LOG(("@R6 DoADPm(%ld)", l)); spoilFRA(); if (t == 0) { warning(WNULLPA); } l = arg_f(l); p = adp(t, l); check_seg(ptr2seg(t), ptr2seg(p), WSEGADP); st_stdp(SP, p); } DoADPs(hob, wfac) long hob; size wfac; { /* ADP f: Add f to pointer on top of stack */ register long l = (S_arg(hob) * wfac); register ptr p, t = st_lddp(SP); LOG(("@R6 DoADPs(%ld)", l)); spoilFRA(); if (t == 0) { warning(WNULLPA); } l = arg_f(l); p = adp(t, l); check_seg(ptr2seg(t), ptr2seg(p), WSEGADP); st_stdp(SP, p); } DoADSl2(arg) size arg; { /* ADS w: Add w-byte value and pointer */ register size l = (L_arg_2() * arg); register long t = spop(arg_wi(l)); register ptr p, s = st_lddp(SP); LOG(("@R6 DoADSl2(%ld)", l)); spoilFRA(); t = arg_f(t); if (s == 0) { warning(WNULLPA); } p = adp(s, t); check_seg(ptr2seg(s), ptr2seg(p), WSEGADP); st_stdp(SP, p); } DoADSm(arg) size arg; { /* ADS w: Add w-byte value and pointer */ register long t = spop(arg_wi(arg)); register ptr p, s = st_lddp(SP); LOG(("@R6 DoADSm(%ld)", arg)); spoilFRA(); t = arg_f(t); if (s == 0) { warning(WNULLPA); } p = adp(s, t); check_seg(ptr2seg(s), ptr2seg(p), WSEGADP); st_stdp(SP, p); } DoADSz() { /* ADS w: Add w-byte value and pointer */ register size l = upop(wsize); register long t = spop(arg_wi(l)); register ptr p, s = st_lddp(SP); LOG(("@R6 DoADSz(%ld)", l)); spoilFRA(); t = arg_f(t); if (s == 0) { warning(WNULLPA); } p = adp(s, t); check_seg(ptr2seg(s), ptr2seg(p), WSEGADP); st_stdp(SP, p); } DoSBSl2(arg) size arg; { /* SBS w: Subtract pointers in same fragment and push diff as size w integer */ register size l = (L_arg_2() * arg); register ptr t = st_lddp(SP); register ptr s = st_lddp(SP + psize); register long w; LOG(("@R6 DoSBSl2(%ld)", l)); spoilFRA(); l = arg_wi(l); check_seg(ptr2seg(t), ptr2seg(s), WSEGSBS); w = sbs(t, s); if (must_test && !(IgnMask&BIT(EIOVFL))) { if (l == 2 && (w < I_MINS2 || w > I_MAXS2)) trap(EIOVFL); } dppop(); dppop(); npush(w, l); } DoSBSz() { /* SBS w: Subtract pointers in same fragment and push diff as size w integer */ register size l = upop(wsize); register ptr t = st_lddp(SP); register ptr s = st_lddp(SP + psize); register long w; LOG(("@R6 DoSBSz(%ld)", l)); spoilFRA(); l = arg_wi(l); check_seg(ptr2seg(t), ptr2seg(s), WSEGSBS); w = sbs(t, s); if (must_test && !(IgnMask&BIT(EIOVFL))) { if (l == 2 && (w < I_MINS2 || w > I_MAXS2)) trap(EIOVFL); } dppop(); dppop(); npush(w, l); }