; IfsBcplUtil.Mu -- Ifs Bcpl runtime utilities (except GetFrame and Return) ; Copyright Xerox Corporation 1979, 1980, 1981 ; Last modified May 3, 1981 3:18 PM by Taft ; Last modified by Taft, March 3, 1980 11:16 AM ; - add ObjCall, STA3JSRI instructions ; Last modified by Wobber, February 20, 1980 12:20 PM ; - renamed NOINT to NOINTR to resolve name conflict ; Last modified by Butterfield, February 20, 1980 9:21 PM ; - use runtime dispatch #77 for REGJSR - 2/20/80 ; - remove String and NewFrame and move XFrame - 11/29 ; - make NewFrame be XFrame - 10/29 ; - have jsr .+ go to String - 10/29 ; - add Xjmp0-3, XReturn, NewFrame, XFrame, and String - 8/20 ; - add extended emulator: don't PREDEF NOVEM, and START, RAMCYCX, and TRAP1; ; change SHIFT; and delete RAMRET, TORAM, and TRAP1 label - 8/20 ; - return to START or StartX depending on call - 8/15 ; - use XMAR for PC related fetches - 8/15 ; - use XBcplUtility, trap BcplUtility - 8/2 ; - reorder the uCalls - 8/1/79 ; Derived from BcplUtil.mu: ; Last modified October 16, 1977 6:38 PM ; All Bcpl runtime utilities in this module are invoked by an opcode ; of the form XXnnn, where XX is the opcode for the main dispatch in RamTrap ; and nnn is the DISP field used for sub-dispatching here. !377,100,Lq0.6, Lq1.6, Lq0.5, Lq1.5, Lq0.4, Lq1.4, Lq0.3, Lq1.3, Lq0.2, Lq1.2, Lq0.1, Lq1.1, , Sq0.7, Sq1.7, Sq0.6, Sq1.6, Sq0.5, Sq1.5, Sq0.4, Sq1.4, Sq0.3, Sq1.3, Sq0.2, Sq1.2, Sq0.1, Sq1.1, , Xjmp0, Xjmp1, Xjmp2, Xjmp3, Ior, Xor, Eqv, Mult,DivRem, Rem, Lsh, Rsh, Branch,Lookup, ,Finish, Abort,LongJump, ,MulPlus, Snq0, Snq1, Ly01, Ly10, Sy01, Sy10,XReturn, , XFrame, , , , , , ,REGJSR; ; RamTrap dispatches to BcplUtility and XBcplUtility ; ********** ; For debugging: trap if XBcplUtility executed in XM ; !1,2, NonZeroBankReg, ZeroBankReg; ; XBcplUtility: ; MAR _ 177740; Make sure the emulator bank register is zero ; T_ 17; ; L_ MD AND T; ; SH=0; ; :NonZeroBankReg; [NonZeroBankReg, ZeroBankReg] ; NonZeroBankReg: :TRAP1X; ; ZeroBankReg: ; ********** XBcplUtility: SINK_DISP, BUS, TASK; Branch on sub-code :Lq0.6; BcplUtility: :TRAP1X; trap any old callers ; LongJump ; Jumps to AC3 + @AC3 ; Calling sequence is: ; jsr @355 ; target-. (i.e., a self-relative pointer) LongJump: XMAR_T_AC3; LongJ1: NOP; L_MD+T, TASK; ; Some useful exit sequences %300,321,21, Start2,,,MultDnX; (binary xx00x1xxx1 and xx11x1xxx1) !11,2, Start3,StartX; (even and an odd with 10 bit on) ; These exits can be used only by BcplUtility routines. ; If the BcplUtility routine was called by a BcplUtil trap opcode ; (from bank 0) then IDISP ors 10 into NEXT. ; If it was called by a page 0 JSR caught by the extended emulator ; then IDISP ors 1 into NEXT. Start0: PC_L; Branch here having done L_ new PC; Start1: L_PC, IDISP, TASK; ; Here after executing L_ new PC, TASK. ; If a NEXT[9] branch is pending then return to extended emulator ; else return to standard emulator. Start2: PC_L, :Start3; [Start3, StartX] Start3: SWMODE, :START; returning to ROM0 ; Note: instruction at START in RAM itself branches to START. ; Branch ; Calling sequence is: ; lda 0 switchon value ; jsr @350 ; value of last case ; number of cases ; lastTarget-. ; ... ; firstTarget-. ; return here if out of range, AC0 unchanged !1,2, Bran0, Bran1; !1,2, Bran2, Bran3; Branch: XMAR_T_AC3; Fetch value of last case L_2+T; AC3_L; AC3_ address of first branch table entry T_AC0; Value we are branching on L_MD-T; L_ lastCase-value, carry_ lastCase ge value XMAR_T_AC3-1; Fetch number of cases T_LREG, L_LREG+T, ALUCY; T_ lastCase-value, L_ AC3+(lastCase-value)-1 SAD_L, :Bran0; [Bran0, Bran1] Save address-1 of branch table entry ; Value greater than last case, take out of range exit. Bran0: L_T_MD, :Bran1a; Finish fetch of numCases, turn off ALUCY ; Value le last case, test number of cases Bran1: L_MD-T-1, T_MD; L_ numCases-(lastCase-value)-1, T_ numCases Bran1a: L_AC3+T, ALUCY, TASK; Carry if numCases gr (lastCase-value) AC3_L, :Bran2; [Bran2, Bran3] Adr of inst after branch table ; Value in range, execute branch. ; SAD/ address-1 of branch table entry Bran3: XMAR_T_SAD+1, :LongJ1; Just like LongJump ; Value less than first case, take out of range exit. Bran2: L_AC3, IDISP, :Start2; ; Lookup ; Calling sequence is: ; lda 0 switchon value ; jsr @351 ; number of cases ; case value 1 ; target1-. ; ... ; case value n ; targetn-. ; return here if out of range !1,2, Look0, Look1; !1,2, Look2, Look3; Lookup: XMAR_T_AC3; Fetch number of cases NOP; L_MD+T, T_MD; L_ AC3+numCases, T_ numCases L_LREG+T+1, TASK; L_ AC3+(2*numCases)+1 AC1_L; Save for end test Look0: XMAR_T_AC3+1; Increment pointer, fetch next case value L_AC1-T; Test for end T_AC0, L_T, SH=0; T_ switchon value AC3_L, :Look2; [Look2, Look3] Look2: L_MD-T; Compare switchon value with case L_AC3+1, SH=0, TASK; Increment pointer again AC3_L, :Look0; [Look0, Look1] ; Found matching case value. AC3/ address of dispatch for case. Look1: XMAR_T_AC3, :LongJ1; Just like LongJump ; Lookup failed. AC3/ adr of inst after lookup table Look3: L_AC3, TASK, :Start0; ; Right shift ; Computes ac0 _ ac0 rshift ac1 ; Called by jsr @347 ; Note that shift count may be either positive or negative !1,2, RshPos, RshNeg; !1,2, RshG16, RshL16; !1,2, RshG8, RshL8; !17,10, Rsh0, Rsh1, Rsh2, Rsh3, Rsh4, Rsh5, Rsh6, Rsh7; Use the last 10 of 20 !1,1, RshN1; !1,1, LtoAC0; Rsh: L_T_AC1; Shift count negative? L_17-T, SH<0; 16 or greater? L_10 AND T, ALUCY, :RshPos; [RshPos, RshNeg] 8 or greater? RshPos: L_7 AND T, SH=0, :RshG16; [RshG16, RshL16] Compute count mod 8 RshL16: T_177400, :RshG8; [RshG8, RshL8] ; Shift count in range 8 to 15. Start by right-shifting 8 RshG8: L_AC0.T; AC0_L LCY 8; RshL8 can do the rest since Rsh0-7 are !17,10 ; Shift count less than 8. Branch on shift count (mod 16) RshL8: SINK_AC1, BUS; L_AC0, :Rsh0; ; This shift table is also used in the Lq0.n series of instructions Rsh7: AC0_L RSH 1; Lq0.6: L_AC0, TASK; Rsh6: AC0_L RSH 1; Lq0.5: L_AC0, TASK; Rsh5: AC0_L RSH 1; Lq0.4: L_AC0, TASK; Rsh4: AC0_L RSH 1; Lq0.3: L_AC0, TASK; Rsh3: AC0_L RSH 1; Lq0.2: L_AC0, TASK; Rsh2: AC0_L RSH 1; Lq0.1: L_AC0, TASK; Rsh1: AC0_L RSH 1, :Bran2; Do PC_AC3 and go to START or StartX ; Shift count 0, do nothing Rsh0: L_AC3, IDISP, :Start2; Do PC_L and go to START or StartX ; Shift count 16 or greater, return zero RshG16: L_0, TASK, :LtoAC0; [LtoAC0, LtoAC0] (Rsh1 instead of LtoAC0?) LtoAC0: AC0_L, :Bran2; Do PC_AC3 and go to START or StartX ; Shift count negative. Convert to Left Shift RshNeg: L_0-T, TASK; [RshN1, RshN1] Negate shift count RshN1: AC1_L, :Lsh; ; Right shift constant amount ; Computes ac0 _ ac0 rshift n (n in range 1 to 7) ; Calling sequence is: ; lda 0 value ; jsr 314 - 2*n ; (dispatches into Lq0.n table, above) ; Right shift constant amount ; Computes ac1 _ ac1 rshift n (n in range 1 to 7) ; Calling sequence is: ; lda 1 value ; jsr 315 - 2*n Lq1.6: L_AC1; AC1_L RSH 1; Lq1.5: L_AC1; AC1_L RSH 1; Lq1.4: L_AC1; AC1_L RSH 1; Lq1.3: L_AC1; AC1_L RSH 1; Lq1.2: L_AC1; AC1_L RSH 1; Lq1.1: L_AC1, TASK; AC1_L RSH 1, :Bran2; Do PC_AC3 and go to START or StartX ; Left shift ; Computes ac0 _ ac0 lshift ac1 ; called by jsr @346 ; Note that shift count may be either positive or negative !1,2, LshPos, LshNeg; !1,2, LshG16, LshL16; !1,2, LshG8, LshL8; !7,10, Lsh0, Lsh1, Lsh2, Lsh3, Lsh4, Lsh5, Lsh6, Lsh7; !1,1, LshN1; Lsh: L_T_AC1; Shift count negative? L_17-T, SH<0; 16 or greater? L_10 AND T, ALUCY, :LshPos; [LshPos, LshNeg] 8 or greater? LshPos: L_7 AND T, SH=0, :LshG16; [LshG16, LshL16] Compute count mod 8 LshL16: T_377, :LshG8; [LshG8, LshL8] ; Shift count in range 8 to 15. Start by left-shifting 8 LshG8: T_AC0.T; SINK_LREG, L_T, BUS, TASK; Branch on shift count mod 8 AC0_L LCY 8, :Lsh0; ; Shift count less than 8. Branch on shift count LshL8: SINK_AC1, BUS, TASK; :Lsh0; Lsh7: L_AC0; AC0_L LSH 1; Lsh6: L_AC0; AC0_L LSH 1; Lsh5: L_AC0; AC0_L LSH 1; Lsh4: L_AC0; AC0_L LSH 1; Lsh3: L_AC0; AC0_L LSH 1; Lsh2: L_AC0; AC0_L LSH 1; Lsh1: L_AC0, TASK; AC0_L LSH 1, :Bran2; Do PC_AC3 and go to START or StartX ; Shift count 0, do nothing Lsh0: L_AC0, TASK, :LtoAC0; ; Shift count 16 or greater, return zero LshG16: L_0, TASK, :LtoAC0; [LtoAC0, LtoAC0] ; Shift count negative. Convert to Right Shift LshNeg: L_0-T, TASK; [LshN1, LshN1] Negate shift count LshN1: AC1_L, :Rsh; ; Ior ; Computes ac0 _ ac0 % ac1 ; Called by jsr @340 Ior: T_AC1; L_AC0 OR T, TASK, :LtoAC0; ; Xor ; Computes ac0 _ ac0 xor ac1 ; Called by jsr @341 Xor: T_AC1; Xor1: L_AC0 XOR T, TASK, :LtoAC0; ; Eqv ; Computes ac0 _ ac0 eqv ac1 ; Called by jsr @342 Eqv: T_AC1; L_ALLONES XOR T; ac0 eqv ac1 = ac0 xor (not ac1) T_LREG, :Xor1; ; MulPlus ; Computes ac0 _ ac3 _ (ac1*@ac3)+ac0 ; Calling sequence is: ; lda 0 addend ; lda 1 multiplicand ; jsr @357 ; multiplier ; return here with result in ac0 and ac3 !1,2, MPNoAd, MPAdd; !1,2, MPLoop, MPDone; MulPlus: XMAR_AC3; Start fetch of multiplier L_AC3+1; Compute return pc PC_L; L_MD, BUSODD, :MPLp1; Test low bit of multiplier ; MulPlus loop. During each iteration, the multiplier is right-shifted 1 ; and the multiplicand is left-shifted 1. The loop terminates when the ; multiplier becomes zero. This is good because in the standard use of ; MulPlus the multiplier is typically a small integer. MPLoop: L_AC3, BUSODD; Test low bit of multiplier MPLp1: AC3_L RSH 1, :MPNoAd; [MPNoAd, MPAdd] Shift it out ; Multiplier bit was 0, don't add but just shift multiplicand MPNoAd: L_AC1, SH=0, TASK, :MPShft; Test for no more bits in multiplier ; Multiplier bit was 1, add multiplicand to product MPAdd: T_AC1; Multiplicand L_AC0+T; Add to partial product AC0_L, L_T, TASK; L_ multiplicand MPShft: AC1_L LSH 1, :MPLoop; [MPLoop, MPDone] Shift multiplicand left ; Here when done MPDone: L_AC0, IDISP; Copy result to ac3 AC3_L, :Start3; ; Mult ; Computes (ac0,ac1) _ ac0*ac1 ; Called by jsr @343 !1,2, DoMul, NoMul; !1,2, MNoAdd, MAdd; !1,2, NoSpil, Spill; %20,337,317, MultLp, MultDn; (binary xx11x01111 and xx11x11111) Mult: L_AC0-1, BUS=0; Get multiplicand-1, test for zero SAD_L, L_0, :DoMul; [DoMul, NoMul] Save it away DoMul: AC0_L; Init partial product to 0 L_disp.300+1, TASK; top two bits determine return IR_LREG; Init loop count; done when it reaches X20 ; Multiply loop MultLp: L_AC1, BUSODD; Test low bit of multiplier T_AC0, :MNoAdd; [MNoAdd, MAdd] Get partial product ; Multiplier bit was 1, add multiplicand to product MAdd: L_T_SAD+T+1; Add multiplicand to partial product L_AC1, ALUCY; Low part of partial product ; Multiplier bit was 0, just shift multiplicand and partial product MNoAdd: AC1_L MRSH 1, L_T, T_0, :NoSpil; [NoSpil, Spill] Spill: T_ONE; Carry into high partial product NoSpil: AC0_L MRSH 1; L_DISP+1, BUS, TASK; Check and update loop count IR_LREG, :MultLp; [MultLp, MultDn] MultDn if DISP was X20 ; Here when done MultDn: SINK_DISP, BUS; top two bits of DISP to go to START or StartX L_AC3, :Start2; [Start2, MultDnX] MultDnX if DISP is 321 MultDnX: PC_L, :StartX; ; Here when multiplicand is zero, just return zero NoMul: AC1_L, :Bran2; ; DivRem (and Rem, which is needed by the extended emulator) ; Computes ac1 _ ac0/ac1 and ac0 _ ac0 rem ac1 (signed) ; Called by jsr@344 or jsr@345 !1,2, DvsPos, DvsNeg; !1,2, DndPos, DndNeg; !1,2, NoSub, DoSub; !1,2, DivLp, DivDn; !1,2, RemPos, RemNeg; !1,2, QuoPos, QuoNeg; Rem: :DivRem; the extended emulator needs this DivRem: L_T_AC1; Fetch divisor SAD_L, SH<0; Save it, test sign XREG_L, L_0-T, :DvsPos; [DvsPos, DvsNeg] Save original divisor DvsNeg: SAD_L; Negative, negate divisor DvsPos: L_T_AC0; Fetch dividend PC_L, L_0-T, SH<0; Save it, test sign :DndPos; [DndPos, DndNeg] Init loop count DndNeg: T_LREG; Negative, negate dividend DndPos: L_20; Init loop count XH_L, L_0, :DivLp0; Init high dividend ; Divide loop DivLp: L_AC0; Current high dividend T_AC1; Current low dividend and quotient DivLp0: AC0_L MLSH 1, L_T; Shift another bit into high dividend AC1_L LSH 1; Shift a zero into quotient T_SAD; Divisor L_AC0-T, T_AC0; Try to subtract divisor from high dividend AC0_L, ALUCY; Store dividend assuming subtract ok L_XH-1, :NoSub; [NoSub, DoSub] Decrement and test loop count ; Subtract ok, put a 1 in the quotient DoSub: XH_L; Update loop count L_AC1+1, SH=0, TASK; Change quotient bit to 1 AC1_L, :DivLp; [DivLp, DivDn] Branch if done ; Subtract not ok, restore old dividend and leave quotient bit 0 NoSub: XH_L, L_T, SH=0, TASK; Update loop count AC0_L, :DivLp; [DivLp, DivDn] Restore AC0, branch if done ; Here when done. Fix up signs and exit DivDn: L_PC; Get original dividend T_AC0, SH<0; Test sign L_0-T, T_0, :RemPos; [RemPos, RemNeg] RemNeg: AC0_L, T_0-1; Was negative, negate remainder RemPos: L_XREG XOR T; Get divisor sign, xor with dividend T_AC1, SH<0; Test sign L_0-T, TASK, :QuoPos; QuoNeg: AC1_L, :Bran2; Negate quotient QuoPos: :Bran2; Set PC_AC3 and go to START or StartX ; Sq0 ; Left shifts data a constant amount, then stores in partial-word field ; in same manner as Snq0. ; Executes @ac1 _ (@ac1 & not @ac3) + ((ac0 lshift n) & @ac3) ; Calling sequence is: ; lda 0 value (right-justified) ; lda 1 address of word being stored into ; jsr 333 - 2*n (n is number of left shifts desired, in range 0-7) ; mask word (ones in field being stored into, zeroes elsewhere) ; returns here Sq0.7: L_AC0; AC0_L LSH 1; Sq0.6: L_AC0; AC0_L LSH 1; Sq0.5: L_AC0; AC0_L LSH 1; Sq0.4: L_AC0; AC0_L LSH 1; Sq0.3: L_AC0; AC0_L LSH 1; Sq0.2: L_AC0; AC0_L LSH 1; Sq0.1: L_AC0, TASK; AC0_L LSH 1, :Snq0; ; Snq0 ; Stores partial-word field into a structure. ; Executes @ac1 _ (@ac1 & not @ac3) + (ac0 & @ac3) ; Calling sequence is: ; lda 0 value (must be bit-aligned with field being stored into) ; lda 1 address of word being stored into ; jsr @360 ; mask word (ones in field being stored into, zeroes elsewhere) ; returns here Snq0: XMAR_AC3; Fetch mask L_AC1; Address of word being stored into Snq0a: T_MD; MAR_LREG; Fetch word being stored into AC1_L; Save address (in case came from Snq1) L_MD AND NOT T; Zero bits to be changed MAR_AC1; Start to store back updated word T_AC0.T; Mask out extraneous bits in new value L_LREG+T, TASK; Merge new bits into old word MD_LREG; Store back in memory L_AC3+1, IDISP, :Start2; PC_AC3+1 and go to START or StartX ; Sq1 ; Left shifts data a constant amount, then stores in partial-word field ; in same manner as Snq1. ; Executes @ac0 _ (@ac0 & not @ac3) + ((ac1 lshift n) & @ac3) ; Calling sequence is: ; lda 1 value (right-justified) ; lda 0 address of word being stored into ; jsr 334 - 2*n (n is number of left shifts desired, in range 0-7) ; mask word (ones in field being stored into, zeroes elsewhere) ; returns here Sq1.7: L_AC1; AC1_L LSH 1; Sq1.6: L_AC1; AC1_L LSH 1; Sq1.5: L_AC1; AC1_L LSH 1; Sq1.4: L_AC1; AC1_L LSH 1; Sq1.3: L_AC1; AC1_L LSH 1; Sq1.2: L_AC1; AC1_L LSH 1; Sq1.1: L_AC1, TASK; AC1_L LSH 1, :Snq1; ; Snq1 ; Stores partial-word field into a structure. ; Executes @ac0 _ (@ac0 & not @ac3) + ac1 & @ac3 ; Calling sequence is: ; lda 1 value (must be bit-aligned with field being stored into) ; lda 0 address of word being stored into ; jsr @360 ; mask word (ones in field being stored into, zeroes elsewhere) ; returns here Snq1: XMAR_AC3; Fetch mask L_AC1; Get value T_AC0; Get address AC0_L, L_T, :Snq0a; Swap them and join common code ; Load byte from array ; Loads the ac1'th byte from the array pointed to by ac0 ; and returns it right-justified in ac0. ; Called by jsr @362 ; Note: ac1 may be negative. !1,2, Ly01P, Ly01N; !1,2, Ly01L, Ly01R; Ly01: L_AC1; Get index T_AC0, SH<0; Get address, test for negative index MTEMP_L RSH 1, :Ly01P; [Ly01P, Ly01N] Divide index by 2 Ly01N: T_77777+T+1; Negative index, extend sign of index/2 Ly01P: MAR_MTEMP+T; Positive index, start fetch SINK_AC1, BUSODD; Which byte? T_377, :Ly01L; [Ly01L, Ly01R] Ly01L: L_MD AND NOT T, TASK; Left byte, mask and swap to right AC0_L LCY 8, :Bran2; Ly01R: L_MD AND T, TASK, :LtoAC0; Right byte, mask and store ; Load byte from array ; Loads the ac0'th byte from the array pointed to by ac1 ; and returns it right-justified in ac1. ; Called by jsr @363 ; Note: ac0 may be negative. !1,2, Ly10P, Ly10N; !1,2, Ly10L, Ly10R; Ly10: L_AC0; Get index T_AC1, SH<0; Get address, test for negative index MTEMP_L RSH 1, :Ly10P; [Ly10P, Ly10N] Divide index by 2 Ly10N: T_77777+T+1; Negative index, extend sign of index/2 Ly10P: MAR_MTEMP+T; Positive index, start fetch SINK_AC0, BUSODD; Which byte? T_377, :Ly10L; [Ly10L, Ly10R] Ly10L: L_MD AND NOT T, TASK; Left byte, mask and swap to right AC1_L LCY 8, :Bran2; Ly10R: L_MD AND T, TASK; Right byte, mask and store AC1_L, :Bran2; ; Store byte into array ; Stores the byte now contained in frame temp 3 (ac2!3) into ; the ac1'th byte of the array pointed to by ac0. ; Called by jsr@364 ; Note: ac1 may be negative. !1,2, Sy01P, Sy01N; !1,2, Sy01L, Sy01R; Sy01: L_AC1; Get index T_3, SH<0; Frame offset, test for negative index MAR_AC2+T, :Sy01P; [Sy01P, Sy01N] Start fetch of byte to store Sy01N: MTEMP_L MRSH 1, :Sy01A; Negative index, divide by 2 and extend sign Sy01P: MTEMP_L RSH 1; Positive index, just divide by 2 Sy01A: T_MTEMP; Get word index L_AC0+T; Compute address of word T_MD; Here comes the byte to store MTEMP_L; Save word address MAR_MTEMP; Fetch word being stored into SINK_AC1, BUSODD; Which byte? Sy01C: L_377 AND T, T_377, :Sy01L; [Sy01L, Sy01R] Isolate byte being stored Sy01L: AC1_L LCY 8; Storing into left byte, swap halves L_MD AND T, :Sy01B; Zero left byte of word being stored into Sy01R: AC1_L; Storing into right byte, already set up L_MD AND NOT T; Zero right byte of word being stored into Sy01B: MAR_MTEMP; Start store T_LREG; Existing contents to preserve L_AC1 OR T, TASK; Merge old and new bytes MD_LREG, :Bran2; Finish store, then PC_AC3 and go to START or StartX ; Store byte into array ; Stores the byte now contained in frame temp 3 (ac2!3) into ; the ac0'th byte of the array pointed to by ac1. ; Called by jsr@365 ; Note: ac0 may be negative. !1,2, Sy10P, Sy10N; Sy10: L_AC0; Get index T_3, SH<0; Frame offset, test for negative index MAR_AC2+T, :Sy10P; [Sy10P, Sy10N] Start fetch of byte to store Sy10N: MTEMP_L MRSH 1, :Sy10A; Negative index, divide by 2 and extend sign Sy10P: MTEMP_L RSH 1; Positive index, just divide by 2 Sy10A: T_MTEMP; Get word index L_AC1+T; Compute address of word T_MD; Here comes the byte to store MTEMP_L; Save word address MAR_MTEMP; Fetch word being stored into SINK_AC0, BUSODD, :Sy01C; Which byte? Join common code