/***************************************************************************\ * * * S19 Interpreter Bootstrap for m68HC11 MCUs * * * * written by and Copyright (c) Triffid_Hunter, 2005-2006 * * * * This software is released under the GNU General Public License, available * * at http://www.gnu.org/copyleft/gpl.html * * * * This basically means that you may use, modify and distribute this * * software free of charge, but any person recieving this software from you * * must also recieve the source code used to create it, as well as all * * rights to do the same. * * * * This is a layman's interpretation provided for convenience. For the full, * * correct license, read the GNU GPL at http://www.gnu.org/copyleft/gpl.html * * * \***************************************************************************/ /***************************************************************************\ * * * If you use any JMP or JSR instructions, relocation won't work properly. * * I've had to string together two BRAs to avoid a JMP in quite a few * * places, since a BRA can only go +127/-128 bytes. * * * * BAUD can be changed on line 78 at setserial * * * \***************************************************************************/ .nolist .include "hbincludes/6811regs.asm" .include "hbincludes/hbmemmap.asm" .include "hbincludes/hbregs.asm" .list .ifndef DEBUG_STYLE DEBUG_STYLE=0 .endif STATE_WAIT_S =0x00 STATE_WAIT_SNUM =0x10 STATE_WAIT_FILLDATA =0x20 STATE_GET_HALF_BYTE =0x01 .section .data .ifdef ENABLE_RELOCATE reloc_target: .rept 0x100 .byte 0 .endr .endif byte_temp: .word 0 _snum: .byte 0 _slen: .byte 0 _saddr: .word 0 _sdata: .rept 0x10 .byte 0 .endr END_USED_RAM: .section .page0 .global ENTRYPT ENTRYPT: start: /* put IOBase into X for ext. addressing mode */ LDX #IOBase /* Initialize HPRIO: special test mode & expanded mode */ LDAA #SMOD. + MDA. STAA HPRIO_,X /* Initialize the stack */ LDS #MACHINE_STACK setserial: /* initialize serial subsystem */ LDAB #BAUD_2400 STAB BAUD_,X LDAB #SCCR2_ENABLEBOTH STAB SCCR2_,X /* send 0xAA to say we've started booting ok */ LDAB #0xAA BRCLR SCSR_,X TDRE. . STAB SCDR_,X /**/ /* work out where we are: BSR pushes the address of the next instruction onto the stack for us */ BSR get_loc get_loc: PULA PULB /* D (AABB) now contains the address of get_loc, subtract to get address of start. */ SUBB #get_loc /* D now contains *start */ /* send our location to the host */ BRCLR SCSR_,X TDRE. . STAA SCDR_,X BRCLR SCSR_,X TDRE. . STAB SCDR_,X /* register ourselves as interrupt vector */ STD RESETINT .ifdef ENABLE_RELOCATE do_relocate: /* skip if we've already relocated */ TSTA BNE end_relocate /* put *start into X */ XGDX /* get target location */ LDY #reloc_target /* copy 256 bytes */ LDAA #00 BSR bulkcopy /* and jump */ JMP reloc_target end_relocate: .endif generic_error: CLRA LDY #_slen get_chars: .if DEBUG_STYLE==1 /* tell host what we want */ BRCLR SCSR_,X TDRE. . STAA SCDR_,X .endif /* wait for it */ BRCLR SCSR_,X RDRF. . LDAB SCDR_,X /* test if we're grabbing a nibble */ BITA #STATE_WAIT_FILLDATA BEQ inter_expecting_S_or_SNUM /* if result is zero, no match */ /* if so, */ expecting_hex: /* if its less than an '0', its invalid, maybe a newline? */ CMPB #'0' BLO check_if_got_all_data /* if its more than a '9', may be a letter, check */ CMPB #'9' BHI is_not_numeric /* its a number. subtract '0' so '0' becomes 0 and branch */ SUBB #'0' BRA nibble_in_b_ok_and_adjusted /* lower_than_0: /* check for < ord(32) * CMPB #0x20 BHI generic_error /* if not, error * CMPA #STATE_WAIT_FILLDATA BNE generic_error */ check_if_got_all_data: /* got something resembling a newline, check pointer is past start of data */ CPY #_sdata /* if not, error */ BLO generic_error /* branch if lower or same */ /* if so, work out what to do with data */ LDAB _snum .if DEBUG_STYLE==2 /* tell host what our snum is */ BRCLR SCSR_,X TDRE. . STAB SCDR_,X .endif CMPB #'9' BEQ is_an_S9 CMPB #'1' BNE generic_error is_an_S1: /* load data length */ LDAA _slen /* chop address,checksum */ SUBA #3 /* save X */ PSHX /* get data pointer */ LDX #_sdata /* set destination pointer */ LDY _saddr /* call copy routine */ BSR bulkcopy /* restore X */ PULX /* reset status, wait for next data */ inter_generic_error: BRA generic_error /* bulk copy routine. copy up to 256 bytes from anywhere to anywhere */ /* have # bytes in A, source in X and dest in Y before coming here */ bulkcopy: /* read a byte into B from *X */ LDAB ,X /* store it at *Y */ STAB ,Y .if DEBUG_STYLE==2 /* tell host what data we're copying */ PSHX LDX #IOBase BRCLR SCSR_,X TDRE. . STAB SCDR_,X PULX .endif /* increment pointers */ INX INY /* decrement counter */ DECA /* if non-zero after decrement, loop */ BNE bulkcopy /* and return */ RTS inter_expecting_S_or_SNUM: BRA expecting_S_or_SNUM inter_get_chars: BRA get_chars is_an_S9: .if DEBUG_STYLE==2 /* load address */ LDD _saddr /* tell host where we're going */ BRCLR SCSR_,X TDRE. . STAA SCDR_,X BRCLR SCSR_,X TDRE. . STAB SCDR_,X /* swap into Y */ XGDY .else /* load address */ LDY _saddr .endif /* jump to the address in Y that we loaded above */ JSR ,Y /* reset status, resume waiting for data */ BRA generic_error is_not_numeric: /* if lower than 'A' or higher than 'F', error */ CMPB #'A' BLO generic_error CMPB #'F' BHI generic_error /* subtract 'A'-10, so that 'A' becomes 0xA */ SUBB #'A' - 0x0A nibble_in_b_ok_and_adjusted: /* sanity check */ /* ANDB #0x0F */ /* test what kind of nibble this is */ BITA #STATE_GET_HALF_BYTE /* if its high (1st) nibble, branch */ BEQ high_1st_nibble low_2nd_nibble: /* else or with previous high nibble, */ ORAB ,Y .if DEBUG_STYLE==1 /* tell host what we see */ BRCLR SCSR_,X TDRE. . STAB SCDR_,X .endif /* overwrite old data */ STAB ,Y /* check if we're beyond the expected length yet */ /* save X */ PSHX /* load data pointer */ LDX #_slen /* load length */ LDAB ,X /* add them */ ABX /* save in temp */ STX byte_temp /* restore X */ PULX /* compare Y to len+*len */ CPY byte_temp /* finish if higher or same */ BHS check_if_got_all_data /* increment write pointer */ INY /* mark 'wait for next high nibble' */ LDAA #STATE_WAIT_FILLDATA /* and return */ BRA inter_get_chars high_1st_nibble: /* got a high nibble */ /* move it to proper location */ LSLB LSLB LSLB LSLB /* store */ STAB ,Y /* mark 'wait for low half' */ LDAA #STATE_GET_HALF_BYTE + STATE_WAIT_FILLDATA /* and return */ BRA inter_get_chars expecting_S_or_SNUM: /* not grabbing nibbles */ /* check if we're waiting for an SNUM */ TSTA BNE check_if_snum /* waiting for 'S' */ CMPB #'S' /* if not 'S', wait again */ BNE inter_get_chars LDAA #STATE_WAIT_SNUM BRA inter_get_chars check_if_snum: /* we got an 'S' last byte, check what this is */ CMPB #'1' BEQ is_snum /**/ /* BNE inter_generic_error /**/ CMPB #'9' /* BEQ is_snum /**/ BNE inter_generic_error /**/ /* error: not recognised as '1' or '9' */ /* BRA inter_generic_error /**/ is_snum: .if DEBUG_STYLE==2 /* tell host what our snum is * BRCLR SCSR_,X TDRE. . STAB SCDR_,X /**/ .endif STAB _snum LDY #_slen LDAA #STATE_WAIT_FILLDATA BRA inter_get_chars