;----------------------------------------------------------------- ; 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 , 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 _ (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'