home *** CD-ROM | disk | FTP | other *** search
- *
- * MapRZ2.asm CN20.12.95-02.01.95
- *
-
- MACHINE 68030
-
-
- ;*** Exec function offsets ***
-
- Supervisor equ -$001E
- Disable equ -$0078
- Enable equ -$007E
- AllocMem equ -$00c6
- FreeMem equ -$00d2
- CloseLibrary equ -$019e
- OpenLibrary equ -$0228
-
-
- ;*** other constants ***
-
- RB_BOARDADDRESS equ $2E ;offset in RetinaBase
- RB_SEG_ADDRESS equ $32 ;offset in RetinaBase
-
- MEMF_PUBLIC equ (1<<0)
-
- SIZE_32K equ $00008000
- SIZE_4M equ $00400000
-
- MASK_32K equ $00007fff
- MASK_128K equ $0001ffff
- MASK_4M equ $003fffff
-
- RETINAMEMSIZE equ SIZE_4M ;maximum amount of memory is 4 Mb
-
- RETINA_REGNUM equ $43C4 ;choose a Retina hardware register at BoardAddress + this offset
- RETINA_REGVAL equ $03C4 ;access the chosen Retina hardware register
-
- SEG_PTR_0H equ $18 ;Retina register numbers for RETINA_REGNUM
- SEG_PTR_0L equ $19 ;(used to control the 64k memory window)
- SEG_PTR_1H equ $1c
- SEG_PTR_1L equ $1d
- SEG_MODE equ $1e
- SEG_CTRL1 equ $2
- SEG_CTRL2 equ $20
- SEG_CTRL3 equ $26
-
- MASK_SEG_MODE equ %00001100 ;bits not used for segment mode
- MODE_TWO_SEG equ %11010011 ;sets two 32k segments mode
-
- SEG_0_OFFSET equ $00010000 ;offsets of 32K segments
- SEG_1_OFFSET equ $00018000 ;relative to Retina board address
-
-
- ;*** constants for MMU usage ***
-
- TIA equ 8 ; 4Gb / 256 = 16Mb
- TIB equ 6 ; 16Mb / 64 = 256Kb
- TIC equ 3 ;256Kb / 8 = 32Kb
- TID equ 0 ;(no D-Level used)
-
- PAGE_SHIFT equ 15 ;2^15 = 32K
- PAGE_SIZE equ 1<<PAGE_SHIFT ;one page is 32k big
-
- A_ENTRIES equ (1<<TIA) ;number of table entries at each level
- B_ENTRIES equ (1<<TIB)
- C_ENTRIES equ (1<<TIC)
-
- A_TSIZE equ A_ENTRIES*4 ;size of one table at each level
- B_TSIZE equ B_ENTRIES*4 ;(using short descriptors)
- C_TSIZE equ C_ENTRIES*4
-
- C_PSIZE equ PAGE_SIZE ;size of pages at each level
- B_PSIZE equ C_PSIZE<<TIC
- A_PSIZE equ B_PSIZE<<TIB
-
- A_OFFSET equ 0 ;offsets in table mem block
- ;
- B_16M1_OFFSET equ A_OFFSET + A_TSIZE ;first 16 Mb (standard Amiga mem)
- B_16M2_OFFSET equ B_16M1_OFFSET + B_TSIZE :second 16 Mb (used for Retina)
- ;
- C_AC1_OFFSET equ B_16M2_OFFSET + B_TSIZE ;AutoConfig 00e80000-00ebffff
- C_AC2_OFFSET equ C_AC1_OFFSET + C_TSIZE ;AutoConfig 00ec0000-00efffff
- C_RB_OFFSET equ C_AC2_OFFSET + C_TSIZE ;mirrored Retina board
- C_RL_OFFSET equ C_RB_OFFSET + C_TSIZE ;4Mb linear Retina RAM
- ;
- TABLE_SIZE equ C_RL_OFFSET + 16*C_TSIZE ;end and size of table
-
- A_START equ $00000000 ;table entries point to these
- ;addresses in the logical mem space
- B_16M1_START equ $00000000 ;
- B_16M2_START equ $01000000 ;
- ;
- C_AC1_START equ $00e80000 ;
- C_AC2_START equ $00ec0000 ;
- C_RB_START equ $01000000 ;
- C_RL_START equ $01c00000 ;
-
- PAGE_PTR_MASK equ $FFFFFF00 ;low descriptor byte is not part of ptr
- TABLE_PTR_MASK equ $FFFFFFF0 ;low 4 bits are not part of ptr
- TABLE_ALIGN equ $10 ;tables have to be aligned at 16 bytes boundary
-
- PG_CI equ 1<<6 ;page attributes: cache inhibit
- PG_M equ 1<<4 ;modified
- PG_U equ 1<<3 ;used
- PG_WP equ 1<<2 ;write protect
-
- SHORT_INVALID equ $BAD00000 ;DT bits = 00 = INVALID
-
- DT_INVALID equ $0 ;descriptor types: invalid descriptor
- DT_PAGE equ $1 ;page descriptor
- DT_VALID_4BYTE equ $2 ;table pointer to short table
- DT_VALID_8BYTE equ $3 ;table pointer to long table
-
- TC_ENABLE equ 1<<31 ;codes for TC register
- TC_PSIZE equ (%1111)<<20 ;select 32K pages
- TC_TIA equ TIA<<12
- TC_TIB equ TIB<<8
- TC_TIC equ TIC<<4
- TC_TID equ TID
-
-
-
-
- SECTION segment0,CODE
-
- ;************
- ;main program
- ;************
-
- main movem.l D2-D7/A2-A6,-(SP) ;save regs
-
- bsr retina_addr ;read Retina board address
- tst.l d0
- bne 1$
-
- bsr alloc_mem ;allocate memory
- tst.l d0
- bne 1$
-
- bsr gen_MMU_tree ;generate MMU tree
-
- bsr turn_it_on ;turn mapping on
-
- movem.l (SP)+,D2-D7/A2-A6 ;restore regs
- moveq #0,d0 ;returncode = 0,
- rts
-
- 1$ movem.l (SP)+,D2-D7/A2-A6 ;restore regs
- moveq #-1,d0 ;returncode = -1,
- rts
-
-
-
-
- ;************************
- ;get Retina board address
- ;************************
-
- retina_addr ;open RetinaBase
- lea RetinaName,a1
- moveq #3,d0
- move.l (4).w,a6
- jsr OpenLibrary(a6)
- move.l d0,RetinaBase
- beq 1$
-
- ;get address
- move.l d0,a0
- move.l RB_BOARDADDRESS(a0),BoardAddress
-
- ;close RetinaBase
- move.l RetinaBase,a1
- move.l (4).w,a6
- jsr CloseLibrary(a6)
-
- moveq #0,d0
- rts
-
- 1$ moveq #-1,d0
- rts
-
-
-
-
- ;***************
- ;allocate memory
- ;***************
-
- alloc_mem ;allocate memory
- move.l (4).w,a6
- move.l #end_bus_err_handler,d0
- sub.l #bus_err_handler,d0
- add.l #TABLE_ALIGN+TABLE_SIZE,d0
- move.l d0,BlockSize
- move.l #MEMF_PUBLIC,d1
- jsr AllocMem(a6)
- move.l d0,MemBlock
- beq 1$
-
- ;align table at 16 bytes boundary
- and.l #TABLE_PTR_MASK,d0
- add.l #TABLE_ALIGN,d0
- move.l d0,TableStart
-
- ;remember end of table / begin of own Bus Error handler
- add.l #TABLE_SIZE,d0
- move.l d0,HandlerStart
-
- moveq #0,d0
- rts
-
- 1$ moveq #-1,d0
- rts
-
-
-
-
- ;*****************
- ;generate MMU tree
- ;*****************
-
- gen_MMU_tree move.l TableStart,a3 ;start of whole tree (stays in a3 until end of subroutine)
-
- ;A table
- move.l a3,a0
- move.w #A_ENTRIES,d0
- move.l #DT_PAGE+A_START,d1
- 1$ move.l d1,(a0)+
- add.l #A_PSIZE,d1
- subq.w #1,d0
- bne 1$
-
- ;A exceptions
- move.l a3,d0
- add.l #DT_VALID_4BYTE+B_16M1_OFFSET,d0
- move.l d0,(a3) ;pointer to B_16M1
- add.l #B_TSIZE,d0
- move.l d0,4(a3) ;pointer to B_16M2
-
-
- ;B_16M1 table
- move.l a3,a2
- add.l #B_16M1_OFFSET,a2 ;start of B_16M1 table
-
- move.l a2,a0
- move.w #B_ENTRIES,d0
- move.l #DT_PAGE+B_16M1_START,d1
- 2$ move.l d1,(a0)+
- add.l #B_PSIZE,d1
- subq.w #1,d0
- bne 2$
-
- ;B_16M1 exceptions
- move.l a2,a0 ;don't cache chip RAM
- move.w #$200000/B_PSIZE,d0 ;number of chip RAM pages
- 3$ add.l #PG_CI,(a0)+
- subq.w #1,d0
- bne 3$
-
- add.l #PG_CI,$00bc0000/B_PSIZE*4(a2) ;don't cache CIAs
- add.l #PG_CI,$00dc0000/B_PSIZE*4(a2) ;don't cache hardware clock and custom chips
-
- move.l a3,d0
- add.l #DT_VALID_4BYTE+C_AC1_OFFSET,d0
- move.l d0,C_AC1_START/B_PSIZE*4(a2) ;pointer to C_AC1
- add.l #C_TSIZE,d0
- move.l d0,C_AC2_START/B_PSIZE*4(a2) ;pointer to C_AC2
-
- add.l #PG_WP,$00f80000/B_PSIZE*4(a2) ;write protect ROM
- add.l #PG_WP,$00fc0000/B_PSIZE*4(a2) ;(FastROM option would be useful!)
-
-
- ;B_16M2 table
- move.l a3,a2
- add.l #B_16M2_OFFSET,a2 ;start of B_16M2 table
-
- move.l a2,a0
- move.w #B_ENTRIES,d0
- 4$ move.l #SHORT_INVALID,(a0)+
- subq.w #1,d0
- bne 4$
-
- ;B_16M2 exceptions
- move.l a3,d0
- add.l #DT_VALID_4BYTE+C_RB_OFFSET,d0
- move.l d0,(a2) ;pointer to C_RB
-
- move.l a2,a0
- add.l #(C_RL_START-B_16M2_START)/B_PSIZE*4,a0
- move.l a3,d1
- add.l #DT_VALID_4BYTE+C_RL_OFFSET,d1
- move.w #RETINAMEMSIZE/B_PSIZE,d0
-
- 5$ move.l d1,(a0)+ ;16 pointers to C_RL
- add.l #C_TSIZE,d1
- subq.w #1,d0
- bne 5$
-
-
- ;C_AC tables
- move.l a3,a2
- add.l #C_AC1_OFFSET,a2 ;start of C_AC table
-
- move.l a2,a0
- move.w #C_ENTRIES*2,d0
- move.l #DT_PAGE+PG_CI+C_AC1_START,d1
- 6$ move.l d1,(a0)+
- add.l #C_PSIZE,d1
- subq.w #1,d0
- bne 6$
-
- ;C_AC things to remember
- move.l BoardAddress,d0
- sub.l #C_AC1_START,d0
- moveq #PAGE_SHIFT-2,d1
- lsr.l d1,d0 ;divide by page size and multiply by 4 to get long word offset
- add.l a2,d0
- move.l d0,MMU_RB
-
- move.l d0,a0 ;remember valid MMU_RB table entries
- lea ValidMMU_RB,a1
- move.l (a0)+,(a1)+
- move.l (a0)+,(a1)+
- move.l (a0)+,(a1)+
- move.l (a0),(a1)
-
-
- ;C_RB table
- move.l a3,a2
- add.l #C_RB_OFFSET,a2 ;start of C_RB table
-
- move.l a2,a0
- move.w #C_ENTRIES,d0
- 7$ move.l #SHORT_INVALID,(a0)+
- subq.w #1,d0
- bne 7$
-
- ;C_RB exceptions
- move.l a2,a1
- move.l #DT_PAGE+PG_CI,d0
- add.l BoardAddress,d0
- move.l d0,(a1)+
- add.l #PAGE_SIZE,d0
- move.l d0,(a1)+
- add.l #PAGE_SIZE,d0
- move.l d0,(a1)+
- add.l #PAGE_SIZE,d0
- move.l d0,(a1)
-
-
- ;C_RL tables
- move.l a3,a2
- add.l #C_RL_OFFSET,a2 ;start of C_RL table
-
- move.l a2,a0
- move.w #C_ENTRIES*16,d0
- 8$ move.l #SHORT_INVALID,(a0)+
- subq.w #1,d0
- bne 8$
-
- ;C_AC things to remember
- move.l a2,MMU_RL
-
- rts
-
-
-
-
- ;***************
- ;turn mapping on
- ;***************
-
- turn_it_on move.l (4).w,a6
- jsr Disable(a6) ;disable interrupts and task scheduling
-
- lea use_MMU_tree,a5
- jsr Supervisor(a6)
-
- move.l CurrentVBR,a3
- move.l $8(a3),OldHandler ;is called from new handler
-
- lea bus_err_handler,a0
- lea end_bus_err_handler,a1
- move.l HandlerStart,a2
-
- 1$ move.w (a0)+,(a2)+ ;copy handler
- cmp.l a0,a1
- bne 1$
-
- move.l HandlerStart,$8(a3) ;activate own handler
-
- jsr Enable(a6) ;enable interrupts and task scheduling again
- rts
-
-
-
-
- ;turn MMU tree on (Supervisor mode)
-
- use_MMU_tree lea OffTC,a0
- pmove.l (a0),TC ;disable MMU translation
-
- lea NewCRP,a0
- pmove.d (a0),CRP ;point MMU to our new tree
-
- lea NewTC,a0
- pmove.l (a0),TC ;re-enable MMU with new tree
-
- movec.l VBR,d0 ;get VBR pointer
- move.l d0,CurrentVBR
- rte
-
-
-
-
- ;*****************
- ;Bus Error handler
- ;*****************
-
- bus_err_handler movem.l d0-d1/d6-d7/a0-a5,-(sp) ;save regs
- move.l (4+6)*4+$10(sp),d7 ;get faulty address that caused exception
-
- move.l d7,d0 ;faulty address
- and.l #~MASK_128K,d0 ;mask out lower bits; doesn't work, if Retina hardware starts at an odd 64k page!
- cmp.l BoardAddress(pc),d0 ;Retina board hardware accessed?
- beq board_acc ;yes
-
- move.l d7,d0 ;faulty address
- and.l #~MASK_4M,d0 ;mask out lower bits
- cmpi.l #C_RL_START,d0 ;linear Retina RAM accessed?
- beq linear_RAM_acc ;yes
-
- movem.l (sp)+,d0-d1/d6-d7/a0-a5 ;restore regs
- move.l OldHandler(pc),-(sp) ;jump to normal Bus Error handler
- rts
-
-
-
-
- ;Retina board hardware accessed -> change to segmented mode
-
- board_acc ori.w #$0700,SR ;turn interrupts off (are turned on again by rte)
- move.l #C_RB_START+RETINA_REGVAL,a4 ;access the chosen Retina hardware register
- move.l #C_RB_START+RETINA_REGNUM,a5 ;choose Retina hardware register
-
- lea RetinaSegCtrl3(pc),a0
- move.b #SEG_CTRL3,(a5) ;restore Retina registers
- move.b (a0),(a4)
- move.b #SEG_CTRL2,(a5)
- move.b -(a0),(a4)
- move.b #SEG_CTRL1,(a5)
- move.b -(a0),(a4)
- move.b #SEG_MODE,(a5)
- move.b -(a0),(a4)
- move.b #SEG_PTR_1L,(a5)
- move.b -(a0),(a4)
- move.b #SEG_PTR_1H,(a5)
- move.b -(a0),(a4)
- move.b #SEG_PTR_0L,(a5)
- move.b -(a0),(a4)
- move.b #SEG_PTR_0H,(a5)
- move.b -(a0),(a4)
- move.b -(a0),(a5) ;register B after all A registers
-
- lea MMU_S0(pc),a2 ;set MMU_RL table entry 0 invalid
- move.l (a2),a0 ;is entry already invalid?
- cmpa.l #0,a0 ;(movea doesn't set flags, tst.l ax doesn't exist)
- beq 1$ ;yes
- move.l #SHORT_INVALID,(a0) ;mark MMU table entry
- move.l #0,(a2) ;clear pointer
- 1$
- lea MMU_S1(pc),a2 ;set MMU_RL table entry 1 invalid
- move.l (a2),a0 ;is entry already invalid?
- cmpa.l #0,a0 ;(movea doesn't set flags, tst.l ax doesn't exist)
- beq 2$ ;yes
- move.l #SHORT_INVALID,(a0) ;mark MMU table entry
- move.l #0,(a2) ;clear pointer
- 2$
- lea ValidMMU_RB(pc),a0 ;set MMU_RB table entries valid
- move.l MMU_RB(pc),a1
- move.l (a0)+,(a1)+
- move.l (a0)+,(a1)+
- move.l (a0)+,(a1)+
- move.l (a0),(a1)
-
- pflusha ;flush MMU cache
- movem.l (sp)+,d0-d1/d6-d7/a0-a5 ;restore regs
- rte ;restart instruction
-
-
-
-
- ;linear Retina RAM accessed
-
- linear_RAM_acc ori.w #$0700,SR ;turn interrupts off (are turned on again by rte)
- move.l #C_RB_START+RETINA_REGVAL,a4 ;access the chosen Retina hardware register
- move.l #C_RB_START+RETINA_REGNUM,a5 ;choose Retina hardware register
-
- move.l MMU_S0(pc),d0 ;is linar mode already on? (tst.b d(pc) doesn't exist)
- bne linear_is_on ;yes
- move.l MMU_S1(pc),d0 ;is linar mode already on? (tst.b d(pc) doesn't exist)
- bne linear_is_on ;yes
-
-
- ;change to linear mode
-
- lea RetinaRegB(pc),a0 ;save Retina registers
- move.b (a5),(a0)+ ;register B before all A registers
- move.b #SEG_PTR_0H,(a5)
- move.b (a4),(a0)+
- move.b #SEG_PTR_0L,(a5)
- move.b (a4),(a0)+
- move.b #SEG_PTR_1H,(a5)
- move.b (a4),(a0)+
- move.b #SEG_PTR_1L,(a5)
- move.b (a4),(a0)+
- move.b #SEG_MODE,(a5)
- move.b (a4),(a0)+
- move.b (a4),d0 ;set two 32k segments mode
- and.b #MASK_SEG_MODE,d0
- or.b #MODE_TWO_SEG,d0
- move.b d0,(a4)
- move.b #SEG_CTRL1,(a5)
- move.b (a4),(a0)+
- move.b #$f,(a4) ;set normal mode
- move.b #SEG_CTRL2,(a5)
- move.b (a4),(a0)+
- bset.b #1,(a4) ;set normal mode
- move.b #SEG_CTRL3,(a5)
- move.b (a4),(a0)
- andi.b #$f5,(a4) ;set normal mode
-
- move.l #SHORT_INVALID,d0 ;set MMU_RB table entries invalid
- move.l MMU_RB(pc),a0
- move.l d0,(a0)+
- move.l d0,(a0)+
- move.l d0,(a0)+
- move.l d0,(a0)
-
-
- linear_is_on move.l d7,d0 ;faulty address
- and.l #MASK_4M&~MASK_32K,d0 ;mask out upper & lower bits
- move.l d0,d6
- lsr.l #6,d6 ;address for Retina segment pointer
-
- moveq #PAGE_SHIFT-2,d1 ;replaces 'divu.l #C_PSIZE/4,d0'
- lsr.l d1,d0 ;divide by page size and multiply by 4 to get long word offset
- add.l MMU_RL(pc),d0 ;add MMU_RL base address
- move.l d0,a3 ;address in MMU table
-
- move.b NextSegment(pc),d0 ;which segment is next? (tst.b d(pc) doesn't exist)
- bne segment_1
-
-
- ;use segment 0
-
- lea MMU_S0(pc),a2 ;set old MMU_RL table entry 0 invalid
- move.l (a2),a0 ;is entry already invalid?
- cmpa.l #0,a0 ;(movea doesn't set flags, tst.l ax doesn't exist)
- beq 1$ ;yes
- move.l #SHORT_INVALID,(a0) ;mark MMU table entry
- 1$
- move.l ValidMMU_Seg0(pc),(a3) ;set new MMU_RL table entry 0 valid
- move.l a3,(a2) ;store its address in MMU_S0
-
- move.b #SEG_PTR_0L,(a5) ;write address into Retina segment pointer
- move.b d6,(a4)
- lsr.w #8,d6
- move.b #SEG_PTR_0H,(a5)
- move.b d6,(a4)
-
- lea NextSegment(pc),a0 ;set next segment to 1
- move.b #1,(a0)
-
- pflusha ;flush MMU cache
- movem.l (sp)+,d0-d1/d6-d7/a0-a5 ;restore regs
- rte ;restart instruction
-
-
- ;use segment 1
-
- segment_1 lea MMU_S1(pc),a2 ;set old MMU_RL table entry 1 invalid
- move.l (a2),a0 ;is entry already invalid?
- cmpa.l #0,a0 ;(movea doesn't set flags, tst.l ax doesn't exist)
- beq 1$ ;yes
- move.l #SHORT_INVALID,(a0) ;mark MMU table entry
- 1$
- move.l ValidMMU_Seg1(pc),(a3) ;set new MMU_RL table entry 1 valid
- move.l a3,(a2) ;store its address in MMU_S1
-
- sub.w #SIZE_32K>>6,d6 ;subtract 32K>>6 due to second segment
- move.b #SEG_PTR_1L,(a5) ;write address into Retina segment pointer
- move.b d6,(a4)
- lsr.w #8,d6
- move.b #SEG_PTR_1H,(a5)
- move.b d6,(a4)
-
- lea NextSegment(pc),a0 ;set next segment to 0
- move.b #0,(a0)
-
- pflusha ;flush MMU cache
- movem.l (sp)+,d0-d1/d6-d7/a0-a5 ;restore regs
- rte ;restart instruction
-
-
-
-
- ;values provided by the main program
-
- OldHandler ds.l 1 ;pointer to old handler
-
- BoardAddress ds.l 1 ;Retina board address
-
- MMU_RB ds.l 1 ;MMU tables to Retina board
- MMU_RL ds.l 1 ;MMU tables to linear Retina RAM
-
- ValidMMU_RB ds.l 1 ;valid MMU_RB entries to Retina board
- ds.l 1 ;
- ValidMMU_Seg0 ds.l 1 ;valid MMU entry to 32K segment No. 0
- ValidMMU_Seg1 ds.l 1 ;valid MMU entry to 32K segment No. 1
-
-
- ;values filled in by exception handler
-
- MMU_S0 dc.l 0 ;MMU table to segment No. 0 in the linear Retina RAM
- MMU_S1 dc.l 0 ;MMU table to segment No. 1 in the linear Retina RAM
-
- NextSegment dc.b 0 ;next segment to choose
-
- RetinaRegB ds.b 1 ;copies of important Retina registers
- RetinaPtr0h ds.b 1
- RetinaPtr0l ds.b 1
- RetinaPtr1h ds.b 1
- RetinaPtr1l ds.b 1
- RetinaSegMode ds.b 1
- RetinaSegCtrl1 ds.b 1
- RetinaSegCtrl2 ds.b 1
- RetinaSegCtrl3 ds.b 1
-
-
- even
- end_bus_err_handler ;copy handler up to here
-
-
-
-
- ;library names
-
- RetinaName dc.b "retina.library",0
-
-
- ;library base pointers
-
- RetinaBase ds.l 1
-
-
- ;other data
-
- MemBlock ds.l 1 ;reserved mem block
- BlockSize ds.l 1 ;size of mem block
- HandlerStart ds.l 1 ;start of own Bus Error handler
- OffTC dc.l $0 ;TC register value to turn MMU off
- NewTC dc.l TC_ENABLE+TC_PSIZE+TC_TIA+TC_TIB+TC_TIC+TC_TID ;new TC-Register value
- NewCRP dc.l $7FFF<<16+DT_VALID_4BYTE ;\ new CRP-Register value with
- TableStart ds.l 1 ;/ begin of MMU tree
- CurrentVBR ds.l 1
-
- VersionString dc.b "$VER: MapRZ2 1.0 (02.01.95) Christoph Niedeggen",$00
-
- END
-