;Run68013.By Kamran Karimi.simulates 11 68020 instructions. 
;Including: bra.l, extb.l, cas, pack, unpk, link.l, movec, rtd, moves,
;           move ccr,<ea> and trapcc.
;Assembled with AssemPro (Profimat) assembler using an standard A500.
 

ExecBase    equ 4
Allocmem    equ -198
Open        equ -30
Close       equ -36
Read        equ -42
Write       equ -48
OpenLib     equ -408
CloseLib    equ -414
GetMsg      equ -372
OpenWindow  equ -204
CloseWindow equ -72
WaitPort    equ -384
FindTask    equ -294
Forbid      equ -132
Permit      equ -138


CLI_WB:                   ;We must determine where we started from
 move.l  ExecBase,a6
 move.l  #0,a1
 jsr     FindTask(a6)
 move.l  d0,a2
 tst.l   $ac(a2)
 bne     FromCLI
 lea     $5c(a2),a0    ;we started from workbench
 jsr     WaitPort(a6)  ;get the wb message but we do not use it
 lea     $5c(a2),a0
 jsr     GetMsg(a6)

FromCLI:
 move.l  #20,DOSResult   ;DOSResult will give a return value to DOS
Open_DOS:             ;we'll open dos.library
 lea     DOS_Name,a1
 moveq   #0,d0          ;any version
 jsr     OpenLib(a6)
 move.l  d0,DOS_Base
 beq     No_DOS        ;if coud not open DOS. we should exit!
Window_Opening:
 moveq   #0,d0
 move.w  $128(a6),d0
 move.l  DOS_Base,a6
 andi.w  #$000f,d0
 beq     My68000
 move.l  #Consolename1,d1   ;opening awindow
 move.l  #1005,d2        ;mode_old
 jsr     Open(a6)
 move.l  d0,Window_Handler1
 beq     Close_DOS
 move.l  d0,d1
 move.l  #texte1,d2
 move.l  #textend1-texte1,d3
 jsr     Write(a6)          ;write introduction text
 move.l  Window_Handler1,d1
 move.l  #inbuff,d2
 jsr     Read(a6)           ;wait for user to press return
 move.l  Window_Handler1,d1
 jsr     Close(a6)       ;close CON
 bra     Close_DOS
 
My68000:
 move.l  #Consolename2,d1   ;opening awindow
 move.l  #1005,d2        ;mode_old
 jsr     Open(a6)
 move.l  d0,Window_Handler2
 beq     Close_DOS               ;if could noy open CON, then exit
 move.l  Window_Handler2,d1
 move.l  #texte2,d2
 move.l  #textend2-texte2,d3
 jsr     Write(a6)          ;write introduction text
 move.l  #inbuff,d2
 move.l  Window_Handler2,d1
 jsr     Read(a6)           ;read the user's choice to install the code
 moveq   #0,d1
 move.b  inbuff,d1
 cmpi.b  #'i',d1       ;is it 'i' ?
 beq     Install
 cmpi.b  #'I',d1       ;or 'I' ?
 bne     Done         ;if not equal exit
Install:
 move.l  ExecBase,a6
 jsr     Forbid(a6)
 move.l  #EndAddr-BeginAddr,d0  ; length  of actual code in d0 moveq   #0,d1
 jsr     Allocmem(a6)   ;allocate mem
 move.l  d0,NewAddrExcept
 beq     NoMem
 move.l  $c,OldAddrExcept  ;save the original 'address error' address
 movea.l #BeginAddr,a0
 movea.l NewAddrExcept,a1
 move.l  #EndAddr-BeginAddr,d0
 sub.l   #1,d0
copyaddr:
 move.b  (a0)+,(a1)+    ;copy our exception code to the allocated mem
 dbf     d0,copyaddr
 move.l  #EndIllegal-BeginIllegal,d0  ; length  of actual code in d0
 moveq   #0,d1
 jsr     Allocmem(a6)   ;allocate mem
 move.l  d0,NewIllegalExcept
 beq     NoMem
 move.l  #1024,d0      ;there are 255 longword vector addresses
 moveq   #0,d1
 move.l  ExecBase,a6
 jsr     Allocmem(a6)
 move.l  d0,NewVec     ;address of the copied original vectors
 beq     NoMem
 move.l  $10,OldIllegalExcept  ;save the original 'illegal instruction' address
 movea.l #BeginIllegal,a0
 movea.l NewIllegalExcept,a1
 move.l  #EndIllegal-BeginIllegal,d0
 sub.l   #1,d0
copy:
 move.b  (a0)+,(a1)+    ;copy our exception code to the allocated mem
 dbf     d0,copy
 move.l  NewAddrExcept,$c
 move.l  NewIllegalExcept,$10
 move.l  #1023,d0
 movea.l #0,a0
 movea.l NewVec,a1
copy2:
 move.b  (a0)+,(a1)+   ;get a copy of all the vector area contents
 dbf     d0,copy2  
 jsr     Permit(a6)
 move.l  DOS_Base,a6
 move.l  Window_Handler2,d1
 move.l  #text3,d2
 move.l  #textend3-text3,d3
 jsr     Write(a6)            ;write 'Now you can use ... '
 move.l  #inbuff,d2
 move.l  Window_Handler2,d1
 jsr     Read(a6)           ;wait for user to press return
 move.l  #0,DOSResult
 bra     Done

NoMem:
 move.l  ExecBase,a6
 jsr     Permit(a6)
Done:
 move.l  Window_Handler2,d1 
 move.l  DOS_Base,a6
 jsr     Close(a6)       ;close CON

Close_DOS:
 move.l  DOS_Base,a1
 move.l  ExecBase,a6
 jsr     CloseLib(a6)    ;close DOS
No_DOS: 
 move.l  DOSResult,d0
 rts

Consolename1:  dc.b 'CON:80/40/470/80/Run68013',0
Consolename2:  dc.b 'CON:40/40/550/110/Run68013',0,0
DOS_Name:      dc.b 'dos.library',0

texte1:
 dc.b '                     Run68013 ',13,10
 dc.b '             Written By Kamran Karimi',13,10
 dc.b ' This program should only be run on 68000 machines!'
 dc.b 13,10,13,10
 dc.b ' Aborting...',13,10,13,10
 dc.b '                  Press Return to quit...'
 ds.w 0
textend1:

texte2:
 dc.b '                               Run68013',13,10
 dc.b '                      Written By Kamran Karimi',13,10 
 dc.b 'This program allows to use some 68020 instructions on a 68000.',13,10
 dc.b 'Refer to the Run68013.ReadMe file for more information',13,10
 dc.b 'It uses self-modifying code so do not run it if you have a cache'
 dc.b 13,10,13,10
 dc.b 'Enter i to install the code, or Return to quit without installing'
 dc.b 13,10,13,10
 dc.b 'Enter i to install:'
 ds.w 0
textend2:

text3:
 dc.b 13,10,'Now you can use the additional instructions!',13,10
 dc.b '   Press Return...',0
 ds.w 0
textend3:
 

DOS_Base:        dc.l 0
Window_Handler1: dc.l 0
Window_Handler2: dc.l 0
DOSResult:       dc.l 0
inbuff:          dc.b 0,0


BeginAddr:
 movem.l d0/d1/a0/a1/a6,-(a7)
 move.l  ExecBase,a6
 jsr     Forbid(a6)
 movea.l 30(a7),a0
 move.l  a0,d0
 lsr.l   #1,d0
 bcs     OddAddr
 suba.l  #2,a0
 bra     TestAddr
OddAddr:
 suba.l  #1,a0
TestAddr:
 move.w  (a0),d0
 cmpi.w  #$60ff,d0
 beq     B_R_A_L
 bra     IllegaleAddr

B_R_A_L:
 movea.l 30(a7),a0
 move.l  (a0),d0
 adda.l  d0,a0
 move.l  a0,30(a7)
 jsr     Permit(a6)
 movem.l (a7)+,d0/d1/a0/a1/a6
 adda.l  #8,a7         ;remove address error stack frame
 rte


IllegaleAddr:
 jsr     Permit(a6)
 movem.l (a7)+,d0/d1/a0/a1/a6
 move.l  OldAddrExcept(pc),-(a7) ;place address of original except handler
 suba.l  #2,a7                   ;as return address on the stack
 move.w  14(a7),(a7)
 move.l  d0,-(a7)
 move.w  4(a7),d0
 bset    #13,d0
 bclr    #15,d0
 move.w  d0,4(a7)
 move.l  (a7)+,d0
 rte

OldAddrExcept:  dc.l 0
NewAddrExcept:  dc.l 0

EndAddr:


BeginIllegal:        ;determining which command caused exception
 movem.l d0-d7/a0-a6,-(a7)
 move.l  ExecBase,a6
 jsr     Forbid(a6)
 movea.l 62(a7),a0
 move.w  (a0),d3
 move.w  d3,d4
 andi.w  #$f9c0,d3
 cmpi.w  #$08c0,d3
 beq     C_A_S       ;was it CAS
 move.w  d4,d3
 andi.w  #$f1f0,d3
 cmpi.w  #$8180,d3
 beq     U_N_P_K
 move.w  d4,d3
 andi.w  #$f1f0,d3
 cmpi.w  #$8140,d3
 beq     P_A_C_K
 move.w  d4,d3
 andi.w  #$fff8,d3
 cmpi.w  #$4808,d3
 beq     L_I_N_K_L
 move.w  d4,d3
 andi.w  #$f0f8,d3
 cmpi.w  #$50f8,d3     ;TRAPcc ?
 beq     T_R_A_P_C_C
 move.w  d4,d3
 andi.w  #$fe00,d3
 cmpi.w  #$4800,d3     ;EXTB ?
 beq     E_X_T_B
 move.w  d4,d3
 cmpi.w  #$4e74,d3   ;was is RTD?
 beq     R_T_D
 lsr.w   #1,d3
 cmpi.w  #$273d,d3     ;or MOVEC?
 bne     what1
 move.w  60(a7),d0  ;get status register
 btst    #13,d0  ;check if we were in supervisor mode when exception occured
 bne     M_O_V_E_C
 jsr     Permit(a6)
 movem.l (a7)+,d0-d7/a0-a6
 move.l  $20,-(a7)           ;making a fake return address and SR on stack
 suba.l  #2,a7
 move.w  $6(a7),(a7)
 move.l  d0,-(a7)
 move.w  4(a7),d0
 bset    #13,d0    ;supervisor mode
 bclr    #15,d0    ;no trace
 move.w  d0,4(a7)
 move.l  (a7)+,d0
 rte
what1:
 move.w  d4,d3
 lsr.w   #8,d3
 cmpi.w  #$0e,d3    ;was the illegal command MOVES?
 bne     what2
 move.w  60(a7),d0
 btst    #13,d0      ;in supervisor mode
 bne     M_O_V_E_S
 jsr     Permit(a6)
 movem.l (a7)+,d0-d7/a0-a6
 move.l  $20,-(a7)    ;making a fake return address and SR on stack
 suba.l  #2,a7
 move.w  $6(a7),(a7)
 move.l  d0,-(a7)
 move.w  4(a7),d0
 bset    #13,d0    ;supervisor mode
 bclr    #15,d0    ;no trace
 move.w  d0,4(a7)
 move.l  (a7)+,d0
 rte
what2:
 move.w  d4,d3
 lsr.w   #6,d3
 cmpi.w  #$010b,d3         ;was the instruction move ccr,<ea> ?
 beq     M_O_V_E_F_C_C_R

illegale:      ;it was non of them so do the usual exception processing
 jsr     Permit(a6)
 movem.l (a7)+,d0-d7/a0-a6
 move.l  OldIllegalExcept(pc),-(a7) ;place address of original except handler
 suba.l  #2,a7                  ;as return address on the stack
 move.w  $6(a7),(a7)
 move.l  d0,-(a7)
 move.w  4(a7),d0
 bset    #13,d0
 bclr    #15,d0
 move.w  d0,4(a7)
 move.l  (a7)+,d0
 rte



C_A_S:
 move.l  62(a7),a0
 move.w  (a0),d1
 move.w  d1,d2
 andi.w  #$0600,d1
 lsr.w   #5,d1
 lsr.w   #4,d1
 move.w  #0,d3
 cmpi.w  #1,d1
 beq     adjsize
longword:
 cmpi.w  #2,d1
 bne     lng
 move.w  #3,d1
 move.w  #1,d3
 bra     adjsize
lng:
 move.w  #2,d1
 move.w  #2,d3
adjsize:
 lsl.w   #7,d1
 lsl.w   #5,d1
 lsl.w   #6,d3
 lea     EffAddr(pc),a3
 andi.w  #$cfff,(a3)
 or.w    d1,(a3)
 lea     Mov(pc),a3
 andi.w  #$cfff,(a3)
 or.w    d1,(a3)
 lea     Comp(pc),a3
 andi.w  #$fe3f,(a3)
 or.w    d3,(a3)
 lea     Movd0(pc),a3
 andi.w  #$cfff,(a3)
 or.w    d1,(a3)
 move.w  d2,d1
 andi.w  #$003f,d1
 lea     EffAddr(pc),a3
 andi.w  #$ffc0,(a3)
 or.w    d1,(a3)
 andi.w  #$7,d1
 andi.w  #$38,d2
 lsl.w   #2,d1
 lsl.w   #7,d1
 lsl.w   #3,d2
 or.w    d2,d1
 lea     Mov(pc),a3
 move.l  #$4e714e71,2(a3)
 lea     EffAddr(pc),a6
 move.l  #$4e714e71,2(a6)
 andi.w  #$f03f,(a3)
 or.w    d1,(a3)
 lsr.w   #6,d2
 cmpi.w  #$5,d2
 bne     tst21
 lea     NumAdd(pc),a4
 move.l  #6,(a4)       ;it is address reg. indirect with displ.
 move.w  4(a0),2(a3)
 move.w  4(a0),2(a6)
 bra     Here71
tst21:
 lsr.w   #6,d1
 cmpi.w  #$7,d1
 bne     tst31
 lea     NumAdd(pc),a4
 move.l  #6,(a4)
 move.w  4(a0),2(a3)
 move.w  4(a0),2(a6)
 bra     Here71
tst31:
 cmpi.w  #$f,d1
 bne     tst41
 lea     NumAdd(pc),a4
 move.l  #8,(a4)
 move.l  4(a0),2(a3)
 move.l  4(a0),2(a6)
 bra     Here71
tst41:
 lea     NumAdd(pc),a4
 move.l  #4,(a4)
Here71:
 move.l  62(a7),a0
 move.w  2(a0),d4
 move.w  d4,d5
 andi.w  #$7,d4
 lsl.w   #7,d4
 lsl.w   #2,d4
 lea     Comp(pc),a3
 andi.w  #$f1ff,(a3)
 or.w    d4,(a3)
 andi.w  #$01c0,d5
 lsr.w   #6,d5
 lea     Mov(pc),a3
 andi.w  #$fff8,(a3)
 or.w    d5,(a3)
 lea     saveA7(pc),a3
 move.l  a7,(a3)
 movem.l (a7)+,d0-d7/a0-a6
 lea     saved1(pc),a7
 move.l  d0,(a7)
EffAddr:
 move.l  d0,d0     ;move <ea> to savea1
 nop
 nop
 lea     savea1(pc),a7
Movd0:
 move.l  d0,(a7)
                    ;place the operand in savea1
 move.l  saved1(pc),d0
Comp:
 cmp.l   savea1(pc),d0    ;compare savea1 to dc
 lea     SaveVal(pc),a7
 move    SR,(a7)
 bne     NotEQ
Mov:
 move.l  d0,d0     ;move du to <ea>
 nop
 nop
NotEQ:
 move.l  saveA7(pc),a7
 adda.l  #60,a7
 movem.l d0-d7/a0-a6,-(a7)
 move.w  SaveVal(pc),d3
 andi.w  #$000f,d3
 move.w  60(a7),d2
 andi.w  #$fff0,d2
 or.w    d2,d3
 move.w  d3,60(a7)
 move.l  62(a7),d4
 add.l   NumAdd(pc),d4
 move.l  d4,62(a7)
 move.l  ExecBase,a6
 jsr     Permit(a6)
 movem.l (a7)+,d0-d7/a0-a6
 rte

  
  

U_N_P_K:
 move.l  62(a7),a0
 move.w  (a0),d1
 move.w  d1,d2
 andi.w  #$8,d1
 beq     datareg
 move.w  #32,d3
 bra     lab10
datareg:
 move.w  #0,d3
lab10:
 move.w  d2,d1
 andi.w  #$7,d1 
 or.w    d3,d1    ;get source
 lea     Source(pc),a1
 andi.w  #$ffc0,(a1)
 or.w    d1,(a1)
 move.w  d2,d1
 andi.w  #$0e00,d1
 lsl.w   #3,d3
 or.w    d3,d1
 lea     Dest(pc),a1
 andi.w  #$f03f,(a1)
 or.w    d1,(a1)
 lea     saveA7(pc),a3
 move.l  a7,(a3)
 movem.l (a7)+,d0-d7/a0-a6
 lea     SaveVal(pc),a7
Source:
 move.b  d0,(a7)
 move.l  saveA7(pc),a7
 adda.l  #60,a7
 movem.l d0-d7/a0-a6,-(a7)
 move.b  SaveVal(pc),d5
 move.w  d5,d4
 andi.w  #$000f,d5
 andi.w  #$00f0,d4
 lsl.w   #4,d4
 or.w    d4,d5
 move.l  62(a7),a0
 move.w  2(a0),d1
 add.w   d1,d5
 lea     Dest(pc),a3
 move.w  d5,2(a3)
 movem.l (a7)+,d0-d7/a0-a6
Dest:
 move.w  #$0000,d0
 movem.l d0/d1/a0/a1/a6,-(a7)
 move.l  ExecBase,a6
 jsr     Permit(a6)
 move.l  22(a7),d0
 add.l   #4,d0
 move.l  d0,22(a7)
 movem.l (a7)+,d0/d1/a0/a1/a6
 rte



P_A_C_K:
 move.l  62(a7),a0
 move.w  (a0),d1
 move.w  d1,d2
 andi.w  #$8,d1
 beq     datareg20
 move.w  #32,d3
 bra     lab100
datareg20:
 move.w  #0,d3
lab100:
 move.w  d2,d1
 andi.w  #$7,d1 
 or.w    d3,d1    ;get source
 lea     Source20(pc),a1
 andi.w  #$ffc0,(a1)
 or.w    d1,(a1)
 move.w  d2,d1
 andi.w  #$0e00,d1
 lsl.w   #3,d3
 or.w    d3,d1
 lea     Dest20(pc),a1
 andi.w  #$f03f,(a1)
 or.w    d1,(a1)
 lea     saveA7(pc),a3
 move.l  a7,(a3)
 movem.l (a7)+,d0-d7/a0-a6
 lea     SaveVal(pc),a7
Source20:
 move.w  d0,(a7)
 move.l  saveA7(pc),a7
 adda.l  #60,a7
 movem.l d0-d7/a0-a6,-(a7)
 move.w  SaveVal(pc),d5
 move.l  62(a7),a0
 move.w  2(a0),d1
 add.w   d1,d5
 move.w  d5,d6
 andi.w  #$0f00,d6
 lsr.w   #4,d6
 andi.w  #$000f,d5
 or.w    d6,d5
 lea     Dest20(pc),a3
 move.w  d5,2(a3)
 movem.l (a7)+,d0-d7/a0-a6
Dest20:
 move.b  #00,d0
 movem.l d0/d1/a0/a1/a6,-(a7)
 move.l  ExecBase,a6
 jsr     Permit(a6)
 move.l  22(a7),d0
 add.l   #4,d0
 move.l  d0,22(a7)
 movem.l (a7)+,d0/d1/a0/a1/a6
 rte




L_I_N_K_L:
 move.l  62(a7),a0
 move.w  (a0),d1
 andi.w  #$0007,d1
 lea     RetAddr(pc),a3
 move.l  62(a7),(a3)
 lea     MySR(pc),a3
 move.w  60(a7),d0
 move.w  d0,(a3)
 btst    #13,d0
 bne     SuperS1
 move    USP,a1
 lea     savea1(pc),a3  ;save USP
 move.l  a1,(a3)
 suba.l  #4,a1
 lea     MySP(pc),a3
 move    a1,USP
 move.l  a1,(a3)
 bra     DoOr
SuperS1:
 lea     savea1(pc),a3
 move.l  a7,d5
 move.l  d5,(a3)
 add.l   #66,(a3)    ;66 - 4 = 62
 lea     MySP(pc),a3
 move.l  d5,(a3)
 add.l   #62,(a3)
DoOr:
 cmpi.w  #1,d1
 beq     lab2
 lea     mova1(pc),a2
 andi.w  #$fff8,(a2)
 or.w    d1,(a2)+
 lsl.w   #7,d1
 lsl.w   #2,d1
 andi.w  #$f0ff,(a2)
 or.w    d1,(a2)
 lea     saveA7(pc),a3
 move.l  a7,(a3)            ;save a7
 movem.l (a7)+,d0-d7/a0-a6
 lea     saved1(pc),a7
 move.l  a1,(a7)
 movea.l savea1(pc),a1
mova1:
 move.l  a0,-(a1)
 movea.l MySP(pc),a0
 movea.l saved1(pc),a1
 bra     lab1
lab2:
 lea     saveA7(pc),a3
 move.l  a7,(a3)            ;save a7
 movem.l (a7)+,d0-d7/a0-a6
 lea     saved1(pc),a7
 move.l  a0,(a7)
 movea.l savea1(pc),a0
mova0:
 move.l  a1,-(a0)
 movea.l MySP(pc),a1
 movea.l saved1(pc),a0
lab1:
 movea.l saveA7(pc),a7
 adda.l  #60,a7
 movem.l d0-d7/a0-a6,-(a7)
 movea.l RetAddr(pc),a0
 adda.l  #2,a0
 move.l  (a0),d1
 move.w  MySR(pc),d3
 btst    #13,d3
 bne     SuperS2
 move    USP,a1
 adda.l  d1,a1
 move    a1,USP
 bra     fin
SuperS2:
 lea     saved1(pc),a3
 move.l  d1,(a3)
 movem.l (a7)+,d0-d7/a0-a6
 move.l  MySP(pc),a7
 adda.l  saved1(pc),a7
 move.l  RetAddr(pc),-(a7)
 add.l   #6,(a7)           ;link.l requires 6 bytes.
 move.w  MySR(pc),-(a7)
 movem.l d0/d1/a0/a1/a6,-(a7)
 move.l  ExecBase,a6
 jsr     Permit(a6)
 movem.l (a7)+,d0/d1/a0/a1/a6
 rte
fin:
 move.l  RetAddr(pc),d0
 add.l   #6,d0
 move.l  d0,62(a7)
 move.w  MySR(pc),d0
 move.w  d0,60(a7)
 move.l  ExecBase,a6
 jsr     Permit(a6)
 movem.l (a7)+,d0-d7/a0-a6
 rte


T_R_A_P_C_C:
 move.l  62(a7),a0
 move.w  (a0),d0
 move.w  d0,d4
 andi.w  #$0f00,d0
 cmpi.w  #$0000,d0
 beq     GoTrap
 cmpi.w  #$0100,d0
 seq     d5
 lea     bcond(pc),a1
 andi.w  #$f0ff,(a1)
 or.w    d0,(a1)
 andi.w  #$0007,d4
 cmpi.w  #4,d4       ;has a operand
 bne     HasOp
 moveq   #2,d6
 bra     OpFound
HasOp:
 cmpi.w  #2,d4    ;is the operand word?
 bne     long
 moveq   #4,d6
 bra     OpFound
long:
 cmpi.w  #3,d4
 beq     Found
 bra     illegale
Found:
 moveq   #6,d6
 tst.b   d5
 beq     Exit1
OpFound:
 lea     bcond(pc),a2
 move.l  a2,-(a7)
 move.w  64(a7),d2
 bset    #13,d2
 bclr    #15,d2
 move.w  d2,-(a7)
 rte
 nop             ;force the cpu to use the original status register
bcond:
 bcs     GoTrap
Exit1:
 move.l  62(a7),d4         
 add.l   d6,d4
 move.l  d4,62(a7)
 move.l  ExecBase,a6
 jsr     Permit(a6)
 movem.l (a7)+,d0-d7/a0-a6
 rte
GoTrap:
 move.l  62(a7),d2
 add.l   d6,d2
 move.l  d2,62(a7)
 move.l  ExecBase,a6
 jsr     Permit(a6)
 movem.l (a7)+,d0-d7/a0-a6
 move.l  $1c,-(a7) ;place address of original except handler
 suba.l  #2,a7                  ;as return address on the stack
 move.w  $6(a7),(a7)
 move.l  d0,-(a7)
 move.w  4(a7),d0
 bset    #13,d0
 bclr    #15,d0
 move.w  d0,4(a7)
 move.l  (a7)+,d0
 rte


 

E_X_T_B:
 move.l  62(a7),a0
 move.w  (a0),d1
 lea     extw(pc),a1
 andi.w  #$fff8,(a1)
 andi.w  #$0007,d1
 or.w    d1,(a1)
 lea     extl(pc),a1
 andi.w  #$fff8,(a1)
 or.w    d1,(a1)
 movem.l (a7)+,d0-d7/a0-a6
extw:
 ext.w   d0
extl:
 ext.l   d0
 movem.l d0-d7/a0-a6,-(a7)
 move    SR,d0
 andi.w  #$000f,d0
 move.w  60(a7),d1
 andi.w  #$fff0,d1
 or.w    d0,d1
 move.w  d1,60(a7)
 move.l  62(a7),d4         ;get the address of the extb.l instruction
 add.l   #2,d4       ;add 2 so that execution begins with the next opcode
 move.l  d4,62(a7)
 move.l  ExecBase,a6
 jsr     Permit(a6)
 movem.l (a7)+,d0-d7/a0-a6
 rte
 

R_T_D:      ;Syntax: rtd  #<data>
 move.l  62(a7),a0
 adda.l  #2,a0
 moveq   #0,d0
 move.w  (a0),d0    ;d0 = #<data>
 move.w  60(a7),d1
 btst    #13,d1         ;which stack we were using befor the exception?
 bne     SuperStack
 move.l  usp,a6
 move.l  (a6)+,62(a7)  ;place return address on the usp as the except return
 adda.l  d0,a6        ;address on top of the ssp so we'll return there
               ;then add  the number of bytes appropriate to the usp
 move.l  a6,usp
 bra     EndIt
SuperStack:
 move.l  a7,a6
 adda.l  #70,a6 ;60=15 regs*4,2 for SR,4 for illegal inst,addr,4for ret addr
 adda.l  d0,a6
 move.l  66(a7),-(a6)  ;retun address for rtd
 move.w  60(a7),-(a6)  ;SR
 move.l  #14,d4       ;15 regs
 adda.l  #60,a7
cop:
 move.l  -(a7),-(a6)
 dbra    d4,cop
 move.l  a6,a7
EndIt:
 move.l  ExecBase,a6
 jsr     Permit(a6)
 movem.l (a7)+,d0-d7/a0-a6
 rte


M_O_V_E_C:   ;Syntax:movec CR,Rn or movec Rn,CR (CR=a control register)
 move.l  62(a7),a0
 move.w  (a0),d3  ;this is the illegal instruction
 btst    #0,d3
 bne     ToCR
 move.w  2(a0),d3
 move.w  d3,d4
 lea     Source2(pc),a3
 andi.w  #$f03f,(a3)
 btst    #15,d3
 beq     Datareg2
 andi.w  #$7000,d3
 lsr.w   #3,d3
 ori.w   #$0040,d3
 or.w    d3,(a3)
 bra     lab20
Datareg2:
 andi.w  #$7000,d3
 lsr.w   #3,d3
 or.w    d3,(a3)
lab20:
 andi.w  #$0fff,d4     ;get the control register
 cmpi.w  #$0,d4        ;is it SFC?
 bne     nextt1
 movea.l MySFC(pc),a1     ;put its contents in a1
 bra     Here1
nextt1:
 cmpi.w  #$0001,d4     ;is it DFC?
 bne     nextt2
 movea.l MyDFC(pc),a1    ;put it in a1
 bra     Here1
nextt2:
 cmpi.w  #$0800,d4     ;is it USP?
 bne     nextt3
 move    USP,a1        ;put it in a1
 bra     Here1
nextt3:
 cmpi.w  #$0002,d4     ;is it CACR?
 bne     nextt4
 movea.l MyCACR(pc),a1        ;put it in a1
 bra     Here1
nextt4:
 cmpi.w  #$0802,d4     ;is it CAAR?
 bne     nextt5
 movea.l MyCAAR(pc),a1        ;put it in a1
 bra     Here1
nextt5:
 cmpi.w  #$0803,d4     ;is it MSP?
 beq     ssp1
 cmpi.w  #$0804,d4    ;or ISP?
 bne     nextt6
ssp1:
 movea.l a7,a1
 adda.l  #66,a1       ;don't consider the pushed registers!
 bra     Here1
nextt6:
 cmpi.w  #$0801,d4
    ;is it VBR?
 beq     mvbr
 bra     illegale
mvbr:
 movea.l MyVBR(pc),a1    ; put it in a1
Here1:
 lea     SaveVal(pc),a3
 move.l  a1,(a3)
 movem.l (a7)+,d0-d7/a0-a6
Source2:
 move.l  SaveVal(pc),d0
 movem.l d0-d7/a0-a6,-(a7)
 move.l  62(a7),d4         ;get the address of the movec instruction
 add.l   #4,d4       ;add 4 so that execution begins with the next opcode
 move.l  d4,62(a7)
 move.l  ExecBase,a6
 jsr     Permit(a6)
 movem.l (a7)+,d0-d7/a0-a6
 rte

ToCR:
 move.w  2(a0),d3
 move.w  d3,d4
 lea     Source3(pc),a3
 andi.w  #$ffc0,(a3)
 btst    #15,d3
 beq     Datareg3
 andi.w  #$7000,d3
 lsr.w   #5,d3
 lsr.w   #7,d3
 ori.w   #$0008,d3
 or.w    d3,(a3)
 bra     lab30
Datareg3:
 andi.w  #$7000,d3
 lsr.w   #5,d3
 lsr.w   #7,d3
 or.w    d3,(a3)
lab30:
 lea     saveA7(pc),a3
 move.l  a7,(a3)
 lea     saved1(pc),a3
 move.l  d4,(a3)
 movem.l (a7)+,d0-d7/a0-a6
 lea     SaveVal(pc),a7
Source3:
 move.l  d0,(a7)
 move.l  saveA7(pc),a7
 adda.l  #60,a7
 movem.l d0-d7/a0-a6,-(a7)
 move.l  SaveVal(pc),d1
 move.l  saved1(pc),d4
 andi.w  #$0fff,d4
 cmpi.w  #$0,d4
 bne     nextr1
 lea     MySFC(pc),a3
 andi.l  #$7,d1
 move.l  d1,(a3)
 bra     here2
nextr1:
 cmpi.w  #$0001,d4
 bne     nextr2
 lea     MyDFC(pc),a3
 andi.l  #$7,d1
 move.l  d1,(a3)
 bra     here2
nextr2:
 cmpi.w  #$0800,d4
 bne     nextr3
 movea.l d1,a2
 move    a2,USP
nextr3:
 cmpi.w  #$0002,d4
 bne     nextr4
 lea     MyCACR(pc),a3
 andi.l  #$f,d1
 move.l  d1,(a3)
 bra     here2
nextr4:
 cmpi.w  #$0802,d4
 bne     nextr5
 lea     MyCAAR(pc),a3
 move.l  d1,(a3)
 bra     here2
nextr5:
 cmpi.w  #$0803,d4
 beq     ssp2
 cmpi.w  #$0804,d4
 bne     nextr6
ssp2:
 lea     saved1(pc),a3
 move.l  d1,(a3)
 lea     saveA7(pc),a3
 move.l  a7,(a3)
 movem.l (a7)+,d0-d7/a0-a6
 lea     savea1(pc),a7
 move.l  a1,(a7)
 move.l  saved1(pc),a1
 move.l  saveA7(pc),a7
 adda.l  #60,a7
 move.l  2(a7),-(a1)   ;return address
 move.w  (a7),-(a1)   ;status register
 move.l  a1,a7
 move.l  savea1(pc),a1
 movem.l d0-d7/a0-a6,-(a7)
 bra     here2
nextr6:
 cmpi.w  #$0801,d4
 beq     mvbr2
 bra     illegale
mvbr2:
 lea     MyVBR(pc),a3
 move.l  d1,(a3)
 bne     NotZero   ;if new address not zero then copy the 1024 bytes at the
 movea.l #0,a5         ;VBR address to the locations 0-1024
 movea.l NewVec(pc),a4
 move.l  #1023,d4
copy3:
 move.b  (a4)+,(a5)+
 dbf     d4,copy3
 bra     here2
NotZero:
 movea.l MyVBR(pc),a4 ;if the VBR holds 0,then copy the original vectors in
 movea.l #0,a5      ;in its place
 move.l  #1023,d4
copy4:
 move.b  (a4)+,(a5)+
 dbf     d4,copy4
here2:
 move.l  62(a7),d4
 add.l   #4,d4
 move.l  d4,62(a7)
 move.l  ExecBase,a6
 jsr     Permit(a6)
 movem.l (a7)+,d0-d7/a0-a6
 rte



M_O_V_E_S:       ;Syntax:moves Rn,<ea> or moves <ea>,Rn
 move.l  62(a7),a0
 adda.l  #2,a0    ;address of the second word of operand
 move.w  (a0),d3
 btst    #11,d3
 beq     ea2Rn
           ;this is moves.x  Rn,<ea>.first move.x Rn,d0 then move.x d0,<ea>
 moveq   #0,d2      ;we will produce the opcode in d2
 movea.l 62(a7),a0
 move.w  (a0),d3    ;first word in d3
 andi.w  #$00c0,d3     ;determine operation size (.B, .W or .L)
 lsr.w   #6,d3
 cmpi.w  #0,d3
 bne     wl
 move.w  #$1000,d2
 bra     size1
wl:               ;Word or Long
 cmpi.w  #1,d3
 bne     l
 move.w  #$3000,d2
 bra     size1
l:                 ;Long
 move.w  #$2000,d2
size1:
 adda.l  #2,a0
 move.w  (a0),d3    ;second word in d3
 andi.w  #$f000,d3
 lsr.w   #8,d3
 lsr.w   #4,d3
 cmpi.w  #0,d3
 seq     d6      ;was the Rn, d0? if yes, then set d6 to 1
 or.w    d3,d2
 tst.b   d6
 beq     Notd01
 movem.l (a7)+,d0-d7/a0-a6
 movem.l d0-d7/a0-a6,-(a7)
 lea     saved0(pc),a3
 move.l  d0,(a3)
 bra     here3
Notd01:
 lea     CRn2d2,a3
 move.w  d2,(a3)
 lea     saveA7(pc),a3
 move.l  a7,(a3)
 movem.l (a7)+,d0-d7/a0-a6
 lea     savereg(pc),a7
 move.l  d0,(a7)
CRn2d2:  dc.w 0
 lea     saved0(pc),a7
 move.l  d0,(a7)
 move.l  savereg(pc),d0
 move.l  saveA7(pc),a7
 adda.l  #60,a7
 movem.l d0-d7/a0-a6,-(a7)
here3:
 moveq   #0,d2
 movea.l 62(a7),a0
 move.w  (a0),d3
 move.w  d3,d4
 andi.w  #$0007,d3     ;register number of <ea>
 cmpi.w  #0,d3
 seq     d5 ;set if register number=0, if mode=7 then it means Absolut short
 cmpi.w  #1,d3
 seq     d7 ;if reg num=1 and mode =7 then addressing=absolute long
 lsl.w   #8,d3
 lsl.w   #1,d3
 or.w    d3,d2
 move.w  d4,d3
 andi.w  #$0038,d3      ;get the mode in d3 lsr.w   #3,d3
 cmpi.w  #7,d3
 seq     d1     ;if mode=1 then set d1 to 1
 cmpi.w  #5,d3
 bne     gg1
 seq     d6   ;if mode=5 then address reg indirect with displacement
 bra     gg2
gg1:
 cmpi.w  #6,d3
 seq     d6 ;if mode=6 then address reg indirect with index and displacement
gg2:
 lsl.w   #6,d3
 or.w    d3,d2
 move.w  d4,d3
 andi.w  #$00c0,d3       ;get size
 lsr.w   #6,d3
 cmpi.w  #0,d3
 bne     wl2
 ori.w   #$1000,d2
 bra     size2
wl2:
 cmpi.w  #1,d3
 bne     l2
 ori.w   #$3000,d2
 bra     size2
l2:
 ori.w   #$2000,d2
size2:
 tst.b   d6
 beq     NoAdind
 adda.l  #4,a0
 lea     code32(pc),a3
 move.w  (a0),(a3)
 lea     code33(pc),a3
 move.w  #$4e71,(a3)
 lea     NumAdd(pc),a3
 move.l  #6,(a3)
 bra     GoOn5
NoAdind:  ;it is no form of address reg indirect with displacement or index
 tst.b   d1
 beq     NoExt  ;<ea> has no extention words at all (like (An) or (An)+)
 tst.b   d5
 beq     testlong
 adda.l  #4,a0       ;get the extention word
 lea     code32(pc),a3
 move.w  (a0),(a3)       ;move extention word
 lea     code33(pc),a3
 move.w  #$4e71,(a3)  ;move NOP
 lea     NumAdd(pc),a3 ;we must add 6 to the pc to get the next instruction
 move.l  #6,(a3)
 bra     GoOn5
testlong:       ;is it absolute long addressing
 tst.b   d7
 bne     NotIll1
 bra     illegale  ;could not fined a legal addressing
NotIll1:
 adda.l  #4,a0
 lea     code32(pc),a3
 move.l  (a0),(a3)
 lea     NumAdd(pc),a3
 move.l  #8,(a3)
 bra     GoOn5
NoExt:
 lea     code32(pc),a3
 move.l  #$4e714e71,(a3)  ;move two NOPs
 lea     NumAdd(pc),a3
 move.l  #4,(a3)
GoOn5:
 lea     code31(pc),a3
 move.w  d2,(a3)
 lea     saveA7(pc),a3
 move.l  a7,(a3)
 movem.l (a7)+,d0-d7/a0-a6
 lea     savereg(pc),a7
 move.l  d0,(a7)
 move.l  saved0(pc),d0
code31:  dc.w 0
code32:  dc.w 0
code33:  dc.w 0
 move.l  savereg(pc),d0
 move.l  saveA7(pc),a7
 adda.l  #60,a7
 movem.l d0-d7/a0-a6,-(a7)
 move.l  62(a7),d4
 add.l   NumAdd(pc),d4
 move.l  d4,62(a7)
 move.l  ExecBase,a6
 jsr     Permit(a6)
 movem.l (a7)+,d0-d7/a0-a6
 rte

ea2Rn:    ;moves.x <ea>,Rn=move.x <ea>,d0 + move.x d0,Rn
 moveq   #0,d2
 movea.l 62(a7),a0
 move.w  (a0),d3
 move.w  d3,d4
 andi.w  #$003f,d3
 move.w  d3,d2
 move.w  d4,d3
 andi.w  #$0007,d3
 cmpi.w  #0,d3
 seq     d5
 cmpi.w  #1,d3
 seq     d7
 move.w  d4,d3
 andi.w  #$0038,d3
 lsr.w   #3,d3
 cmpi.w  #7,d3
 seq     d1
 cmpi.w  #5,d3
 bne     ff1
 seq     d6
 bra     ff2
ff1:
 cmpi.w  #6,d3
 seq     d6
ff2:
 move.w  d4,d3
 andi.w  #$00c0,d3
 lsr.w   #6,d3
 cmpi.w  #0,d3
 bne     wl3
 ori.w   #$1000,d2
 bra     size3
wl3:
 cmpi.w  #1,d3
 bne     l3
 ori.w   #$3000,d2
 bra     size3
l3:
 ori.w   #$2000,d2
size3:
 tst.b   d6
 beq     NoAdind2
 adda.l  #4,a0
 lea     code42(pc),a3
 move.w  (a0),(a3)
 lea     code43(pc),a3
 move.w  #$4e71,(a3)
 lea     NumAdd(pc),a3
 move.l  #6,(a3)
 bra     GoOn6
NoAdind2:
 tst.b   d1
 beq     NoExt2
 tst.b   d5
 beq     testlong2
 adda.l  #4,a0
 lea     code42(pc),a3
 move.w  (a0),(a3)
 lea     code43(pc),a3
 move.w  #$4e71,(a3)
 lea     NumAdd(pc),a3
 move.l  #6,(a3)
 bra     GoOn6
testlong2:
 tst.b   d7
 bne     NotIll2
 bra     illegale
NotIll2:
 adda.l  #4,a0
 lea     code42(pc),a3
 move.l  (a0),(a3)
 lea     NumAdd(pc),a3
 move.l  #8,(a3)
 bra     GoOn6
NoExt2:
 lea     code42(pc),a3
 move.l  #$4e714e71,(a3)
 lea     NumAdd(pc),a3
 move.l  #4,(a3)
GoOn6:
 lea     code41(pc),a3
 move.w  d2,(a3)
 lea     saveA7(pc),a3
 move.l  a7,(a3)
 movem.l (a7)+,d0-d7/a0-a6
 lea     savereg(pc),a7
 move.l  d0,(a7)
code41:  dc.w 0
code42:  dc.w 0
code43:  dc.w 0
 lea     saved0(pc),a7
 move.l  d0,(a7)
 move.l  savereg(pc),d0
 move.l  saveA7(pc),a7
 adda.l  #60,a7
 movem.l d0-d7/a0-a6,-(a7)
here6:
 moveq   #0,d2
 movea.l 62(a7),a0
 move.w  (a0),d3
 andi.w  #$00c0,d3
 lsr.w   #6,d3
 cmpi.w  #0,d3
 bne     wl4
 move.w  #$1000,d2
 bra     size4
wl4:
 cmpi.w  #1,d3
 bne     l4
 move.w  #$3000,d2
 bra     size4
l4:
 move.w  #$2000,d2
size4:
 adda.l  #2,a0
 move.w  (a0),d3
 btst    #15,d3
 seq     d5
 andi.w  #$7000,d3
 move.w  d3,d7
 lsr.w   #8,d7
 lsr.w   #4,d7
 lsr.w   #3,d3
 cmpi.w  #0,d7
 seq     d6
 tst.b   d5
 bne     GoOn4
 ori.w   #$0040,d3
GoOn4:
 or.w    d3,d2
 tst.b   d6
 beq     Notd02
 ori.w   #$0001,d2
 lea     Cd2Rn1(pc),a3
 move.w  d2,(a3)
 lea     saveA7(pc),a3
 move.l  a7,(a3)
 movem.l (a7)+,d0-d7/a0-a6
 lea     savereg(pc),a7
 move.l  d1,(a7)
 move.l  saved0(pc),d1
Cd2Rn1:  dc.w 0
 move.l  savereg(pc),d1
 bra     here4
Notd02:
 lea     Cd2Rn2(pc),a3
 move.w  d2,(a3)
 lea     saveA7(pc),a3
 move.l  a7,(a3)
 movem.l (a7)+,d0-d7/a0-a6
 lea     savereg(pc),a7
 move.l  d0,(a7)
 move.l  saved0(pc),d0
Cd2Rn2:  dc.w 0
 move.l  savereg(pc),d0
here4:
 move.l  saveA7(pc),a7
 adda.l  #60,a7
 movem.l d0-d7/a0-a6,-(a7)
 move.l  62(a7),d4
 add.l   NumAdd(pc),d4
 move.l  d4,62(a7)
 move.l  ExecBase,a6
 jsr     Permit(a6)
 movem.l (a7)+,d0-d7/a0-a6
 rte


M_O_V_E_F_C_C_R:     ;Syntax: move CCR,<ea> = move CCR,d0 + move d0,<ea>
 move.l  62(a7),a0
 move.w  (a0),d1
 move.w  d1,d2
 andi.w  #$7,d1
 andi.w  #$38,d2
 lsl.w   #2,d1
 lsl.w   #7,d1
 lsl.w   #3,d2
 or.w    d2,d1
 lea     From(pc),a3
 move.l  #$4e714e71,4(a3)
 andi.w  #$f03f,(a3)
 or.w    d1,(a3)
 lsr.w   #6,d2
 cmpi.w  #$5,d2
 bne     tst2
 lea     NumAdd(pc),a4
 move.l  #4,(a4)       ;it is address reg. indirect with displ.
 move.w  2(a0),4(a3)
 bra     Here7
tst2:
 lsr.w   #6,d1
 cmpi.w  #$7,d1
 bne     tst3
 lea     NumAdd(pc),a4
 move.l  #4,(a4)
 move.w  2(a0),4(a3)
 bra     Here7
tst3:
 cmpi.w   #$f,d1
 bne      tst4
 lea      NumAdd(pc),a4
 move.l   #6,(a4)
 move.l   2(a0),4(a3)
 bra      Here7
tst4:
 lea      NumAdd(pc),a4
 move.l   #2,(a4)
Here7:
 lea      SaveVal(pc),a4
 move.w   60(a7),d0
 andi.w   #$00ff,d0
 move.w   d0,(a4)
 movem.l  (a7)+,d0-d7/a0-a6
From:
 move.w  SaveVal(pc),d0
 nop
 nop
 movem.l d0-d7/a0-a6,-(a7)
 move.l  62(a7),d4
 add.l   NumAdd(pc),d4
 move.l  d4,62(a7)
 move.l  ExecBase,a6
 jsr     Permit(a6)
 movem.l (a7)+,d0-d7/a0-a6
 rte


OldIllegalExcept:  dc.l 0
NewIllegalExcept:  dc.l 0
NewVec:            dc.l 0
Except:            dc.l 0
MyVBR:             dc.l 0
MySFC:             dc.l 0
MyDFC:             dc.l 0
MyCAAR:            dc.l 0
MyCACR:            dc.l 0
MySR:              dc.w 0
MySP:              dc.l 0
SaveVal:           dc.l 0
RetAddr:           dc.l 0
savea1:            dc.l 0
saved1:            dc.l 0
saved0             dc.l 0
savereg:           dc.l 0
saveA7:            dc.l 0
NumAdd:            dc.l 0

EndIllegal:
 end

