;; crt0.s for old hard disk ;; ;; 68HC16Z1, AT27C1044/AT49F0125 ;; Strange jmp to bank2 which works ;; Strange change of CSBARBT which does not work.. .section .text .global _start .set SIMCR, 0xFA00 .set SYNCR, 0xFA04 .set PORTE0, 0xFA11 ; not aligned .set DDRE, 0xFA15 ; not aligned, ok ;; ??? ;; Port F is a single register that can be accessed in two locations ($YFFA19 and $YFFA1B) .set PORTF0, 0xFA19 ; not aligned .set DDRF, 0xFA1D .set SYPCR, 0xFA21 ; not aligned, ok .set PORTC, 0xFA41 ; not aligned, ok .set CSPAR0, 0xFA44 .set CSPAR1, 0xFA46 .set CSORBT, 0xFA4A .set CSOR0, 0xFA4E ; not aligned, ok .set CSOR1, 0xFA52 .set CSOR2, 0xFA56 .set CSBARBT, 0xFA48 .set CSBAR0, 0xFA4C .set CSBAR1, 0xFA50 .set CSBAR2, 0xFA54 .set PEPAR, 0xFA17 .set PFPAR, 0xFA1F ;; queued serial module .set QSMCR, 0xFC00 .set QILR, 0xFC04 ;; sci .set SCCR0, 0xFC08 .set SCCR1, 0xFC0A .set SCSR, 0xFC0C .set SCDR, 0xFC0E .set PORTQS, 0xFC15 .set PQSPAR, 0xFC16 .set DDRQS, 0xFC17 .set SPCR0, 0xFC18 .set SPCR1, 0xFC1A .set SPCR2, 0xFC1C .set SPCR3, 0xFC1E .set GPTMCR, 0xF900 .set GPTICR, 0xF904 .set DDRGP_PORTGP, 0xF906 .set TMSK1, 0xF920 .set TFLG1, 0xF922 .set PICR, 0xFA22 .set PITR, 0xFA24 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .org 0x0000 _start: .dc.w 0x0FF0 ; ZK/SK/PK .dc.w reset ; PC .dc.w 0xE400 ; initial SP, in SRAM MODULE! .dc.w 0xE000 ; initial IZ, direct page pointer, in SRAM MODULE! .dc.w reset ; 4 Breakpoint (BKPT) .dc.w reset ; 5 Bus Error (BERR) .dc.w reset ; 6 Software Interrupt (SWI) .dc.w reset ; 7 Illegal Instruction .dc.w reset ; 8 Divide by Zero .dc.w 0 ; 9 .dc.w 0 ; 10 .dc.w 0 ; 11 .dc.w 0 ; 12 .dc.w 0 ; 13 .dc.w 0 ; 14 .dc.w reset ; 15 Uninitialized Interrupt .dc.w 0 ; 16 .dc.w reset ; 17 Level 1 Interrupt Autovector .dc.w reset ; 18 Level 2 Interrupt Autovector .dc.w reset ; 19 Level 3 Interrupt Autovector .dc.w reset ; 20 Level 4 Interrupt Autovector .dc.w reset ; 21 Level 5 Interrupt Autovector .dc.w reset ; 22 Level 6 Interrupt Autovector .dc.w reset ; 23 Level 7 Interrupt Autovector .dc.w reset ; 24 Spurious Interrupt .dc.w 0 .dc.w 0 .dc.w 0 .dc.w 0 .dc.w 0 .dc.w 0 .dc.w 0 .dc.w 0 .dc.w 0 .dc.w 0 .dc.w 0 .dc.w 0 .dc.w 0 .dc.w 0 .dc.w 0 .dc.w 0 .dc.w 0 .dc.w 0 .dc.w 0 .dc.w 0 .dc.w 0 .dc.w 0 .dc.w 0 .dc.w 0 .dc.w 0 .dc.w 0 .dc.w 0 .dc.w 0 .dc.w 0 .dc.w 0 .dc.w 0 .dc.w irq_x0 ; 56 User Defined Interrupt Vector 1 .dc.w reset ; 57 User Defined Interrupt Vector 2 .dc.w reset ; 58 User Defined Interrupt Vector 3 .dc.w reset ; 59 User Defined Interrupt Vector 4 .dc.w reset ; 60 User Defined Interrupt Vector 5 .dc.w reset ; 61 User Defined Interrupt Vector 6 .dc.w reset ; 62 User Defined Interrupt Vector 7 .dc.w reset ; 63 User Defined Interrupt Vector 8 .dc.w loc_482 ; 64 User Defined Interrupt Vector 9 .dc.w loc_486 ; 65 User Defined Interrupt Vector 10 .dc.w loc_48A ; 66 User Defined Interrupt Vector 11 .dc.w loc_48E ; 67 User Defined Interrupt Vector 12 .dc.w loc_492 ; 68 User Defined Interrupt Vector 13 .dc.w loc_496 ; 69 User Defined Interrupt Vector 14 .dc.w loc_49A ; 70 User Defined Interrupt Vector 15 .dc.w loc_49E ; 71 User Defined Interrupt Vector 16 .dc.w loc_4A2 ; 72 User Defined Interrupt Vector 17 .dc.w loc_4A6 ; 73 User Defined Interrupt Vector 18 .dc.w loc_4AA ; 74 User Defined Interrupt Vector 19 .dc.w loc_4AE ; 75 User Defined Interrupt Vector 20 .org 0x0200 reset: orp #0xE0 ;; address reg space..? ldab #0xFF tbsk tbek tbzk ;; MM = 1: Internal modules are addressed from $FFF000 - $FFFFFF ldd #0x834E ; EXOFF=1 00000 SHEN=11 SUPV=0 MM=1 00 IARB=1110 std SIMCR ;; Tis register can be written only once following power-on or reset, ;; but can be read at any time. ldab #4 ; HME = Halt Monitor Enable stab SYPCR ;; Setting this to 0 forces reset? ldab #1 ; PC0 ON stab PORTC ;; STACK NOT USABLE HERE!? ;jmp toggle_txd ldd #0x00FB ; 2#00 00 00 00 CS2:11=CS16 CS1:11=CS16 CS0:10=CS8 CSBOOT:11=CS16 std CSPAR0 ldd #0x0100 ; 2#00 00 00 01=ADDR23? 00 00 00 00 std CSPAR1 ldd #0x6870 ; 2#01 10 10 00 01 11 00 00 std CSORBT ; BOOT ldd #0x7870 ; 2#01111000 01110000 std CSOR0 ldd #0x7BB0 ; 2#01111011 10110000 std CSOR1 ldd #5 ; 256k at 0x0000 std CSBARBT ldd #0xFFF8 ; blocksize 2K std CSBAR0 ldd #3 ; blocksize 64K std CSBAR1 ;; RAM!? ldd #4 ; blocksize 128K std CSBAR2 clr PFPAR ; all pins io, no irq ldaa #0x9F ; bit set = output staa DDRF ;; ??? ldaa #0x80 ; PF.7 ON staa PORTF0 ;; ??? jmp 0x20000+xjmp xjmp: ;; OK ;;jmp toggle_txd ;; WHY IS CSBARBT CHANGED?? ;;ldd #0x204 ; A16=1 A15=0 A14=0 A13=00 A12=0 A11=0 100 128K at ????, A23-A17 ;;std CSBARBT ;; NOT OK! ;;jmp toggle_txd ;; RAM!? ldd #0x7BB0 ; 2#01111011 10110000 std CSOR2 ;; OK ;;jmp toggle_txd clr PFPAR ; all pins io, no irq ;; OK ;;jmp toggle_txd ;; ??? ;;clr PORTF0 ; PF.7 OFF ;; NOT OK! ;;jmp toggle_txd ldaa #0x9F ; bit set = output staa DDRF ;; COPY CODE HERE.. ;; OK ;;jmp toggle_txd ;; has no effect on toggle_txd frequency.. ldd #0x7F04 ; 0x7F = double clock speed, 0x04=RSTEN=Reset when clock lost std SYNCR ;; OK ;;jmp toggle_txd ldab #0x30 ; activate /AS (PE5) and /DS (PE4).. stab PEPAR ldab #0x40 ; PE6 ON, LED!? stab PORTE0 ldaa #0xFE ; Pin PE0 is input from jumper? staa DDRE clr PFPAR ldd #0x138 std PICR ldd #0 std PITR ldd #0xF std GPTMCR ldd #0x8640 std GPTICR ldd #0x7C00 ; DDR: 0x7C DATA: 0x00 std DDRGP_PORTGP clrw TMSK1 bclrw TFLG1,#0xFFFF ;; OK ;;jmp toggle_txd ;; IARB - Interrupt Arbitration Identification Number ldd #0xD std QSMCR clr QILR clr PORTQS ldaa #0xFF ; all special function staa PQSPAR ldaa #0xFF ; all outputs? staa DDRQS ldd #0xA102 ; MASTER=1 WOMQ=0 BITS=1000=8 CPOL=0 CPHA=1 BAUD=00000010 std SPCR0 clrw SPCR1 clrw SPCR2 clrw SPCR3 ; QSM COMMAND RAM ldaa #0x73 staa 0xFD40 staa 0xFD41 staa 0xFD42 staa 0xFD43 staa 0xFD44 staa 0xFD45 staa 0xFD46 staa 0xFD47 staa 0xFD48 staa 0xFD49 staa 0xFD4A staa 0xFD4B staa 0xFD4C staa 0xFD4D staa 0xFD4E staa 0xFD4F ;; SRAM at FF:E000, used for stack and data ;; This module contains a 2-Kbyte array of fast (two bus cycle) static RAM, which is especially useful as ;; a location for system stacks and variable storage. SRAM can be mapped to any 2 Kbyte boundary in ;; the address map ;; RAM ARRAY BASE ADDRESS REGISTER HIGH (RAMBAH) ldd #0x00FF std 0xFB04 ;; RAM ARRAY BASE ADDRESS REGISTER LOW (RAMBAL) ldd #0xE000 std 0xFB06 ;; RAM MODULE CONFIGURATION REGISTER (RAMMCR) ldd #0x0A00 std 0xFB00 ;; STACK IS NOW USABLE? ;; TODO: ZERO BSS.. ;; OK jmp toggle_txd jsr sci_init endless1: ;ldx #msg1 ;jsr sci_puts ;ldx #msg2 ;jsr sci_puts bra endless1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; toggle_txd: ; portqs all outputs ldaa #0xFF staa DDRQS ; disable sci ldd #0x0000 std SCCR1 ;; 1 us hi,1 us low at default speed, 526 KHz toggle_txd1: ;; PQS7 (TXD) bset PORTQS,#0x80 ; 8 cycles nop ; 2 cycles nop ; 2 cycles nop ; 2 cycles bclr PORTQS,#0x80 ; 8 cycles bra toggle_txd1 ; 6 cycles rts ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; msg1: .ascii "abcdefghijklmnopqrstuvwxyz" .dc.b 0xD, 0x0A msg2: .ascii "ABCDEFGHIJKLMNOPQRSTUVWXYZ" .dc.b 0xD, 0x0A ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; sci_init: ldd #0x0037 ; 9600 baud @ 16.78 MHz std SCCR0 ldd #0x000C ; 0xC = TE RE, not parity, 1 start bit, 1 stop bit std SCCR1 ; enable the SCI receiver and transmitter rts ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; sci_putchar: brclr SCSR, #0x01, sci_putchar ; wait for TDRE (TDR empty) staa SCDR rts ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; string in x sci_puts: ldaa 0,x beq sci_puts_done bsr sci_putchar ;inx aix #1 bra sci_puts sci_puts_done: rts ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; sci_crlf: ldaa #0x0D bsr sci_putchar ldaa #0x0A bsr sci_putchar rts ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; sci_getchar: brclr SCSR+1, #0x40, sci_getchar ; wait for TC (transmit complete) ldaa SCDR+1 rts ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Shift left: D = E << D shl: TSTD ;Special case (0 bit shift) BEQ shl2 ;Yes, early exit shl1: LSLE ;Shift one bit SUBD #1 ;Reduce count BNE shl1 ;Not finished, continue shl2: TED ;Get result RTS ;; Shift right: D = E >> D shr: TSTD ;Special case (0 bit shift) BEQ shr2 ;Yes, early exit shr1: LSRE ;Shift one bit SUBD #1 ;Reduce count BNE shr1 ;Not finished, continue shr2: TED ;Get result RTS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 16 bit signed Division: D = E / D sdiv: PSHM X ;Save index register XGDX ;X = denominator LDD #1 ;*1 = sign extend EMULS ;Get signex value into E:D EDIVS ;Perform divide BRA div1 ;Return values ;; 16 bit unsigned division: d = E / D div: PSHM X ;Save index register XGDX ;'X' = denominator TED ;Get numerator IDIV ;Perform divide div1: XGDX ;'D' = quotient PULM X ;Restore index register RTS ;; 16 bit Modulus: D = E % D mod: PSHM X ;Save index register XGDX ;'X' = denominator TED ;Get numerator IDIV ;Perform divide PULM X ;Restore index register RTS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; * Signed >, >=, <, <= gt: BSR docomp ;D = E > D BGT ret1 BRA ret0 ge: BSR docomp ;D = E >= D BGE ret1 BRA ret0 lt: BSR docomp ;D = E < D BLT ret1 BRA ret0 le: BSR docomp ;D = E <= D BLE ret1 BRA ret0 ;; * = amd != eq: BSR docomp ;D = E == D BEQ ret1 ;; * FALSE result, D=0, ZF=1 ret0: CLRD RTS ne: BSR docomp ;D = E != D BEQ ret0 ;; * TRUE result, D=1, ZF=0 ret1: LDD #1 RTS ;; * Compare E and D docomp: PSHM D,X ;Save registers TSX ;Address stack CPE 2,X ;Perform compare PULM D,X ;Restore registers RTS ;; * TRUE result, D=1, ZF=0 ;; * Unsigned >, >=, <, <= ugt: BSR docomp ;D = E > D BHI ret1 BRA ret0 uge: BSR docomp ;D = E >= D BHS ret1 BRA ret0 ult: BSR docomp ;D = E < D BLO ret1 BRA ret0 ule: BSR docomp ;D = E <= D BLS ret1 BRA ret0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; loc_482: jmp irq_x1 loc_486: jmp irq_x2 loc_48A: jmp irq_timer loc_48E: jmp irq_x1 loc_492: jmp irq_x3 loc_496: jmp reset loc_49A: jmp irq_x4 loc_49E: jmp reset loc_4A2: jmp reset loc_4A6: jmp irq_x5 loc_4AA: jmp reset loc_4AE: jmp reset ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; irq_x0: rti irq_x1: rti irq_x2: rti irq_x3: rti irq_x4: rti irq_x5: rti irq_timer: rti