;----------------------------------------------------------------- ; MesaXRAM.Mu - Overflow XMesa microcode from ROM1 ; Last modified by Levin - February 27, 1979 5:41 PM ;----------------------------------------------------------------- ; Separate assembly requires... #MesabROM.mu; ;----------------------------------------------------------------- ; Entry Point Definitions: ; ; The definitions below must correspond to those in MesabROM. ;----------------------------------------------------------------- %1,1777,402,BLTintpend,BLTloop; BLTloop must match ramBLTloop %1,1777,404,BLTnoint,BLTint; BLTint must match ramBLTint %1,1777,410,Overflow; must correspond to ramOverflow !7,10,RR,BLTL,WR,,DADD,DSUB,DCOMP,DUCOMP; dispatched in ROM ;----------------------------------------------------------------- ; D o u b l e - P r e c i s i o n A r i t h m e t i c ;----------------------------------------------------------------- ; !1,1,DSUBsub; shake B/A dispatch !3,4,DAStail,,,DCOMPr; returns from DSUBsub !1,1,Dsetstkp; shake ALUCY dispatch !1,1,Setstkp; shake IDISP from BLTnoint Overflow: :RR; dispatch pending ; TASK pending for doubles ;----------------------------------------------------------------- ; DADD - add two double-word quantities, assuming: ; stack contains precisely 4 elements ;----------------------------------------------------------------- ; !1,1,DADDx; shake B/A dispatch !1,2,DADDnocarry,DADDcarry; DADD: T←stk2, :DADDx; T:low bits of right operand DADDx: L←stk0+T; L:low half of sum stk0←L, ALUCY; stash, test carry T←stk3, :DADDnocarry; T:high bits of right operand DADDnocarry: L←stk1+T, :DASCtail; L:high half of sum DADDcarry: L←stk1+T+1, :DASCtail; L:high half of sum ;----------------------------------------------------------------- ; DSUB - subtract two double-word quantities, assuming: ; stack contains precisely 4 elements ;----------------------------------------------------------------- DSUB: IR←msr0, :DSUBsub; ;----------------------------------------------------------------- ; Double-precision subtract subroutine ;----------------------------------------------------------------- !1,2,DSUBborrow,DSUBnoborrow; !7,1,DSUBx; shake IR← dispatch DSUBsub: T←stk2, :DSUBx; T:low bits of right operand DSUBx: L←stk0-T; L:low half of difference stk0←L, ALUCY; borrow = ~carry T←stk3, :DSUBborrow; T:high bits of right operand DSUBborrow: L←stk1-T-1, IDISP, :DASCtail; L:high half of difference DSUBnoborrow: L←stk1-T, IDISP, :DASCtail; L:high half of difference ;----------------------------------------------------------------- ; Common exit code ;----------------------------------------------------------------- DASCtail: stk1←L, ALUCY, :DAStail; carry used by double compares DAStail: T←2, :Dsetstkp; adjust stack pointer Dsetstkp: L←stkp-T, SWMODE, :Setstkp; Setstkp: stkp←L, :romnext; 'next' has proper SWMODE bit ;----------------------------------------------------------------- ; DCOMP - compare two long integers, assuming: ; stack contains precisely 4 elements ; result left on stack is -1, 0, or +1 (single-precision) ; (i.e. result = sign(stk1,,stk0 DSUB stk3,,stk2) ) ;----------------------------------------------------------------- ; !1,1,DCOMPxa; shake B/A dispatch !10,1,DCOMPxb; shake IR← dispatch !1,2,DCOMPnocarry,DCOMPcarry; !1,2,DCOMPgtr,DCOMPequal; DCOMP: IR←T←100000, :DCOMPxa; IR←msr0, must shake dispatch DCOMPxa: L←stk1+T, :DCOMPxb; scale left operand DCOMPxb: stk1←L; L←stk3+T, TASK; scale right operand stk3←L, :DSUBsub; do DSUB, return to DCOMPr DCOMPr: T←stk0, :DCOMPnocarry; L: stk1, ALUCY pending DCOMPnocarry: L←0-1, BUS=0, :DCOMPsetT; left opnd < right opnd DCOMPcarry: L←M OR T; L: stk0 OR stk1 SH=0; DCOMPsetT: T←3, :DCOMPgtr; T: amount to adjust stack DCOMPgtr: L←0+1, :DCOMPequal; left opnd > right opnd DCOMPequal: stk0←L, :Dsetstkp; stash result ;----------------------------------------------------------------- ; DUCOMP - compare two long cardinals, assuming: ; stack contains precisely 4 elements ; result left on stack is -1, 0, or +1 (single-precision) ; (i.e. result = sign(stk1,,stk0 DSUB stk3,,stk2) ) ;----------------------------------------------------------------- DUCOMP: IR←sr3, :DSUBsub; returns to DCOMPr ;----------------------------------------------------------------- ; E m u l a t o r A c c e s s ;----------------------------------------------------------------- ;----------------------------------------------------------------- ; RR - push <emulator register alpha>, where: ; RR is A-aligned (also ensures no pending branch at entry) ; alpha: 1 => wdc, 2 => XTSreg, 3 => XTPreg, 4 => ATPreg, ; 5 => OTPreg ;----------------------------------------------------------------- !7,10,RR0,RR1,RR2,RR3,RR4,RR5,,; RR: SINK←ib, BUS; dispatch on alpha RR0: L←0, SWMODE, :RR0; (so SH=0 below will branch) RR1: L←wdc, SH=0, :romUntail; will go to pushTA RR2: L←XTSreg, SH=0, :romUntail; will go to pushTA RR3: L←XTPreg, SH=0, :romUntail; will go to pushTA RR4: L←ATPreg, SH=0, :romUntail; will go to pushTA RR5: L←OTPreg, SH=0, :romUntail; will go to pushTA ;----------------------------------------------------------------- ; WR - emulator register alpha ← <TOS> (popped), where: ; WR is A-aligned (also ensures no pending branch at entry) ; alpha: 1 => wdc, 2 => XTSreg ;----------------------------------------------------------------- !7,10,WR0,WR1,WR2,,,,,; ; WR: L←ret3, TASK, :Xpopsub; performed in ROM WR: SINK←ib, BUS; dispatch on alpha WR0: SWMODE, :WR0; WR1: wdc←L, :romnextA; WR2: XTSreg←L, :romnextA; ;----------------------------------------------------------------- ; BLT - block transfer ; assumes stack has precisely three elements: ; stk0 - address of first word to read ; stk1 - count of words to move ; stk2 - address of first word to write ; the instruction is interruptible and leaves a state suitable ; for re-execution if an interrupt must be honored. ;----------------------------------------------------------------- !1,2,BLTmore,BLTdone; !1,2,BLTsource,BLTCsource; !1,2,BLTeven,BLTodd; !1,1,BLTintx; shake branch from BLTloop ; Entry sequence in ROM1; actual entry is at BLTloop ;BLT: stk7←L, SWMODE, :BLTx; stk7=0 <=> branch pending ;BLTx: IR←msr0, :ramBLTloop; IR← is harmless BLTloop: L←T←stk1-1, BUS=0, :BLTnoint; BLTnoint: stk1←L, L←BUS AND ~T, IDISP, :BLTmore; L←0 on last iteration (value ; on bus is irrelevant, since T ; will be -1). IDISP on last ; cycle requires that Setstkp ; be odd. BLTmore: T←cp, :BLTsource; BLTsource: MAR←stk0, :BLTupdate; start data source fetch BLTCsource: XMAR←stk0+T, :BLTupdate; start code source fetch BLTupdate: L←stk0+1; stk0←L; update source pointer L←stk2+1; T←MD; source data MAR←stk2; start dest. write stk2←L, L←T; update dest. pointer SINK←NWW, BUS=0, TASK; check pending interrupts MD←M, :BLTintpend; loop or check further BLTintpend: SINK←wdc, BUS=0, :BLTloop; check if interrupts enabled ; Must take an interrupt if here (via BLT or BITBLT) BLTint: SINK←stk7, BUS=0, :BLTintx; test even/odd pc BLTintx: L←mpc-1, :BLTeven; prepare to back up BLTeven: mpc←L, L←0, :BLTodd; even - back up pc, clear ib BLTodd: ib←L, SWMODE; odd - set ib non-zero :romIntstop; ; BLT completed BLTdone: SINK←stk7, BUS=0, SWMODE, :Setstkp; stk7=0 => return to 'nextA'