]> git.gag.com Git - fw/sdcc/commitdiff
xa51, work in progress
authorjohanknol <johanknol@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Thu, 7 Feb 2002 14:16:01 +0000 (14:16 +0000)
committerjohanknol <johanknol@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Thu, 7 Feb 2002 14:16:01 +0000 (14:16 +0000)
git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@1902 4a8a32a2-be11-0410-ad9d-d568d2c75423

20 files changed:
as/xa51/Makefile
as/xa51/bigtest.xa [deleted file]
as/xa51/local_label.xa [deleted file]
as/xa51/mt.xa [deleted file]
as/xa51/paulmon2.xa [deleted file]
as/xa51/todo [deleted file]
as/xa51/xa_asm.l [deleted file]
as/xa51/xa_asm.y [deleted file]
as/xa51/xa_dasm.c [deleted file]
as/xa51/xa_main.c
as/xa51/xa_main.h
as/xa51/xa_rasm.l [new file with mode: 0755]
as/xa51/xa_rasm.y [new file with mode: 0755]
device/examples/xa51/hello.c
src/xa51/gen.c
src/xa51/main.c
support/regression/Makefile
support/regression/ports/xa51/spec.mk [new file with mode: 0755]
support/regression/ports/xa51/support.c [new file with mode: 0755]
support/regression/ports/xa51/uCsim.cmd [new file with mode: 0755]

index 0ed11c76f6493ce84fa94619fc2b981870af93c7..eab05d7123fdc40dbb8683d00fa93cea29b7cea6 100644 (file)
@@ -1,40 +1,34 @@
 CC = gcc
-CFLAGS = -ggdb -O2
+CFLAGS = -ggdb -O2 -Wall
 YACC = bison -y -d
 LEX = flex -i
 LEXLIB = 
 
-xa_asm: xa_main.o xa_asm.tab.o xa_asm.lex.o xa_dasm.o
-       $(CC) -o xa_asm xa_main.o xa_asm.tab.o xa_asm.lex.o xa_dasm.o $(LEXLIB)
-       #strip xa_asm
+xa_rasm: xa_main.o xa_rasm.tab.o xa_rasm.lex.o 
+       $(CC) -o xa_rasm xa_main.o xa_rasm.tab.o xa_rasm.lex.o $(LEXLIB)
+       #strip xa_rasm
 
-xa_asm.lex.o: xa_asm.lex.c xa_asm.tab.h xa_main.h
-       $(CC) $(CFLAGS) -c xa_asm.lex.c
+xa_rasm.lex.o: xa_rasm.lex.c xa_rasm.tab.h xa_main.h
+       $(CC) $(CFLAGS) -c xa_rasm.lex.c
 
-xa_asm.tab.o: xa_asm.tab.c xa_asm.tab.h xa_main.h
-       $(CC) $(CFLAGS) -c xa_asm.tab.c
+xa_rasm.tab.o: xa_rasm.tab.c xa_rasm.tab.h xa_main.h
+       $(CC) $(CFLAGS) -c xa_rasm.tab.c
 
 xa_main.o: xa_main.c xa_main.h
        $(CC) $(CFLAGS) -Wall -c xa_main.c
 
-xa_dasm.o: xa_dasm.c
-       $(CC) $(CFLAGS) -Wall -c xa_dasm.c
+xa_rasm.tab.c xa_rasm.tab.h: xa_rasm.y
+       $(YACC) xa_rasm.y
+       mv y.tab.c xa_rasm.tab.c
+       mv y.tab.h xa_rasm.tab.h
 
-xa_asm.tab.c xa_asm.tab.h: xa_asm.y
-       $(YACC) xa_asm.y
-       mv y.tab.c xa_asm.tab.c
-       mv y.tab.h xa_asm.tab.h
+xa_rasm.lex.c: xa_rasm.l
+       $(LEX) xa_rasm.l
+       mv lex.yy.c xa_rasm.lex.c
 
-xa_asm.lex.c: xa_asm.l
-       $(LEX) xa_asm.l
-       mv lex.yy.c xa_asm.lex.c
-
-all: touch xa_asm
-
-touch:
-       touch xa_asm.y xa_asm.l xa_dasm.c
+all: xa_rasm
 
 clean:
        rm -f *.tab.c *.tab.h *.lex.c *.o *.bak y.output *.hex *.lst *.obj
-       rm -f xa_asm core *~
+       rm -f xa_rasm core *~
 
diff --git a/as/xa51/bigtest.xa b/as/xa51/bigtest.xa
deleted file mode 100644 (file)
index a68df3c..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-
-;this is a comment
-
-        .equ    var, 40
-        .bit    my_bit, var.5  ;this is another comment
-
-       add     r5, r1
-       add     r4l, r2h        ;this is the third comment
-       add     r14, r2
-
-       add     [r5], r11
-       add     [r4], r1h
-
-       add     r2, [r0]
-       add     r4l, [r5]
-
-       add     r3, [r1+54]
-       add     r6h, [r5+31]
-
-       add     [r7+3], r2l
-       add     [r6+2], r5
-
-       add     r4, [r2+5405]
-       add     r3h, [r5+-31321]
-
-       add     [r1+1032], r3l
-       add     [r2+-1232], r7
-
-       add     r1, [r6+]
-       add     r3h, [r2+]
-
-       add     [r5+], r2
-       add     [r1+], r7l
-
-       add     341, r3
-       add     345, r1l
-
-       add.w   r6, 31
-       add.b   r5h, 1029
-
-       add     r3l, #54
-       add     r0, #12411
-
-       add.w   [r7], #4223
-       add.w   [r1], #41122
-
-       add.b   [r1+], #45
-       add.b   [r6+], #-10
-
-       add.b   [r2+42], #41
-       add.w   [r1+89], #3112
-
-       add.b   [r7+32321], #12
-       add.w   [r3+8761], #5891
-
-       add.b   1231, #31
-       add.w   156, #9861
-
-       add     r0, r1
-       mov     [r4+4], r6
-loop:  mov     r2, r1
-       asr     r1, #3
-       mov     r1l, #9
-       mov     [r1+4], r2
-       jmp     loop
-       bov     loop
-
-       addc    r15, r4
-       addc    r11, r10
-       addc.b  [r7+4], #-30
-       addc.b  [r3+], #21
-        addc.w  [r7+4], #-30
-        addc.w  [r3+], #321
-
-       adds    r3, #4
-       adds.w  [r1], #6
-       adds.w  [r0+], #-3
-       adds.w  [r5+4], #2
-       adds.w  [r2+-500], #1
-       adds.w  var, #1
-
-        adds    r3h, #4
-        adds.b  [r1], #6
-        adds.b  [r0+], #-3
-t1:     adds.b  [r5+4], #2
-        adds.b  [r2+-500], #1
-        adds.b  var, #1
-
-t2:    and     [r5+3287], r1l
-       and.w   var, #2011
-
-       anl     c, 43.1
-       anl     c, /my_bit
-
-       asl     r3, r1l
-       asl     r11, r5h
-t65:   asl.d   r4, r1h
-       asl.w   r0, r4l
-       asl.b   r4h, r3l
-        asl     r0, r4l
-
-
-       asl.b   r1l, #6
-       asl.b   r3h, #11
-       asl.w   r1, #3
-       asl.w   r4, #7
-        asl     r1l, #6
-        asl     r3h, #11
-        asl     r1, #3
-        asl     r4, #7
-       asl.d   r2, #9
-       asl.d   r2, #21
-
-       asr     r4l, r1h
-       asr     r4, r1h
-        asr.w   r0, r4l
-        asr.w   r4, #7
-        asr.d   r1, #9
-       asr.d   r6, #14
-       asr.d   r5, #27
-
-       bcc     loop
-t7:    bcs     t65
-       beq     t7
-       bg      t65
-       bge     t1
-       bgt     t1
-       bkpt
-       bl      t7
-       ble     loop
-       blt     loop
-       bmi     t2
-       bne     t1
-       bnv     t65
-       bov     t2
-       bpl     t2
-       br      loop
-       call    t2
-       call    [r1]
-
-
diff --git a/as/xa51/local_label.xa b/as/xa51/local_label.xa
deleted file mode 100644 (file)
index 7d6f551..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-;local lable test... labels consisting of one of more numbers
-;with a dollar sign on the end are considered to be local
-;labels and are unique within a section of code following
-;a normal non-local label
-
-
-        .equ    var, 40
-        .bit    my_bit, var.5  ;this is another comment
-
-begin:
-       add     r5, r1
-       add     r4l, r2h        ;this is the third comment
-       add     r14, r2
-
-00001$:        add     [r5], r11
-       add     [r4], r1h
-
-       jmp     00001$
-       add     r2, [r0]
-       add     r0, r1
-       mov     [r4+4], r6
-       bkpt
-00002$:        mov     r2, r1
-       asr     r1, #3
-       mov     r1l, #9
-       bne     another_function
-       mov     [r1+4], r2
-       jmp     00002$
-       bkpt
-
-
-another_function:
-       add     r4l, [r5]
-       add.b   [r6+], #-10
-00001$: add.b  [r7+32321], #12
-       add.b   1231, #31
-       beq     00001$
-       djnz    r2, 00001$
-       jmp     begin
-
diff --git a/as/xa51/mt.xa b/as/xa51/mt.xa
deleted file mode 100644 (file)
index dfa5ae9..0000000
+++ /dev/null
@@ -1,1425 +0,0 @@
-
-;$include xa-g3.equ    ;will implement included later on
-
-
-; Include file for XA-G3 SFR Definitions
-; Philips Semiconductors. Revision 1.8, 1/21/97
-; $nolist              ;will implement this later on
-
-; Register equates.
-
-acc     reg     R4L          ; for translated 80C51 code
-dpl     reg     R6L          ; for translated 80C51 code
-dph     reg     R6H          ; for translated 80C51 code
-sp      reg     R7           ; for translated 80C51 code
-
-
-; SFR byte and bit definitions.
-
-bcr     sfr     46ah
-btrh    sfr     469h
-btrl    sfr     468h
-cs      sfr     443h
-ds      sfr     441h
-es      sfr     442h
-
-ieh     sfr     427h
-eri0    bit     ieh.0
-eti0    bit     ieh.1
-eri1    bit     ieh.2
-eti1    bit     ieh.3
-
-iel     sfr     426h
-ex0     bit     iel.0
-et0     bit     iel.1
-ex1     bit     iel.2
-et1     bit     iel.3
-et2     bit     iel.4
-ea      bit     iel.7
-
-ipa0    sfr     4a0h
-ipa1    sfr     4a1h
-ipa2    sfr     4a2h
-ipa4    sfr     4a4h
-ipa5    sfr     4a5h
-
-p0      sfr     430h
-p1      sfr     431h
-p2      sfr     432h
-p3      sfr     433h
-p0cfga  sfr     470h
-p1cfga  sfr     471h
-p2cfga  sfr     472h
-p3cfga  sfr     473h
-p0cfgb  sfr     4f0h
-p1cfgb  sfr     4f1h
-p2cfgb  sfr     4f2h
-p3cfgb  sfr     4f3h
-
-pcon    sfr     404h
-idl     bit     pcon.0
-pd      bit     pcon.1
-
-pswh    sfr     401h
-im0     bit     pswh.0
-im1     bit     pswh.1
-im2     bit     pswh.2
-im3     bit     pswh.3
-rs0     bit     pswh.4
-rs1     bit     pswh.5
-tm      bit     pswh.6
-sm      bit     pswh.7
-
-pswl    sfr     400h
-z       bit     pswl.0
-n       bit     pswl.1
-v       bit     pswl.2
-ac      bit     pswl.6
-cy      bit     pswl.7
-
-psw51   sfr     402h
-
-rth0    sfr     455h
-rth1    sfr     457h
-rtl0    sfr     454h
-rtl1    sfr     456h
-
-s0con   sfr     420h
-ri_0    bit     s0con.0
-ti_0    bit     s0con.1
-rb8_0   bit     s0con.2
-tb8_0   bit     s0con.3
-ren_0   bit     s0con.4
-sm2_0   bit     s0con.5
-sm1_0   bit     s0con.6
-sm0_0   bit     s0con.7
-scon    sfr     420h         ; duplicate label for translated 80C51 code.
-ri      bit     scon.0       ; duplicate label for translated 80C51 code.
-ti      bit     scon.1       ; duplicate label for translated 80C51 code.
-rb8     bit     s0con.2      ; duplicate label for translated 80C51 code.
-tb8     bit     s0con.3      ; duplicate label for translated 80C51 code.
-ren     bit     s0con.4      ; duplicate label for translated 80C51 code.
-sm2     bit     s0con.5      ; duplicate label for translated 80C51 code.
-sm1     bit     s0con.6      ; duplicate label for translated 80C51 code.
-sm0     bit     s0con.7      ; duplicate label for translated 80C51 code.
-
-s0stat  sfr     421h
-stint0  bit     s0stat.0
-oe0     bit     s0stat.1
-br0     bit     s0stat.2
-fe0     bit     s0stat.3
-
-s0buf   sfr     460h
-sbuf    sfr     460h         ; duplicate label for translated 80C51 code.
-s0addr  sfr     461h
-s0aden  sfr     462h
-
-s1con   sfr     424h
-ri_1    bit     s1con.0
-ti_1    bit     s1con.1
-rb8_1   bit     s1con.2
-tb8_1   bit     s1con.3
-ren_1   bit     s1con.4
-sm2_1   bit     s1con.5
-sm1_1   bit     s1con.6
-sm0_1   bit     s1con.7
-
-s1stat  sfr     425h
-stint1  bit     s1stat.0
-oe1     bit     s1stat.1
-br1     bit     s1stat.2
-fe1     bit     s1stat.3
-
-s1buf   sfr     464h
-s1addr  sfr     465h
-s1aden  sfr     466h
-
-scr     sfr     440h
-
-ssel    sfr     403h
-r0seg   bit     ssel.0
-r1seg   bit     ssel.1
-r2seg   bit     ssel.2
-r3seg   bit     ssel.3
-r4seg   bit     ssel.4
-r5seg   bit     ssel.5
-r6seg   bit     ssel.6
-eswen   bit     ssel.7
-
-swe     sfr     47ah
-swr     sfr     42ah
-swr1    bit     swr.0
-swr2    bit     swr.1
-swr3    bit     swr.2
-swr4    bit     swr.3
-swr5    bit     swr.4
-swr6    bit     swr.5
-swr7    bit     swr.6
-
-swe1    equ     00000001q    ; bit masks for software interrupt enables.
-swe2    equ     00000010q
-swe3    equ     00000100q
-swe4    equ     00001000q
-swe5    equ     00010000q
-swe6    equ     00100000q
-swe7    equ     01000000q
-
-t2con   sfr     418h
-cprl2   bit     t2con.0
-ct2     bit     t2con.1
-tr2     bit     t2con.2
-exen2   bit     t2con.3
-tclk0   bit     t2con.4
-rclk0   bit     t2con.5
-tclk    bit     t2con.4      ; duplicate label for translated 80C51 code.
-rclk    bit     t2con.5      ; duplicate label for translated 80C51 code.
-exf2    bit     t2con.6
-tf2     bit     t2con.7
-
-t2mod   sfr     419h
-dcen    bit     t2mod.0
-t2oe    bit     t2mod.1
-t2rd    bit     t2mod.2
-tclk1   bit     t2mod.4
-rclk1   bit     t2mod.5
-
-th2     sfr     459h
-tl2     sfr     458h
-t2caph  sfr     45bh
-t2capl  sfr     45ah
-
-tcon    sfr     410h
-it0     bit     tcon.0
-ie0     bit     tcon.1
-it1     bit     tcon.2
-ie1     bit     tcon.3
-tr0     bit     tcon.4
-tf0     bit     tcon.5
-tr1     bit     tcon.6
-tf1     bit     tcon.7
-
-th0     sfr     451h
-th1     sfr     453h
-tl0     sfr     450h
-tl1     sfr     452h
-tmod    sfr     45ch
-tstat   sfr     411h
-t0oe    bit     tstat.0
-t0rd    bit     tstat.1
-t1oe    bit     tstat.2
-t1rd    bit     tstat.3
-
-wdcon   sfr     41fh
-wdtof   bit     wdcon.1
-wdrun   bit     wdcon.2
-pre0    bit     wdcon.5
-pre1    bit     wdcon.6
-pre2    bit     wdcon.7
-
-wdl     sfr     45fh
-wfeed1  sfr     45dh
-wfeed2  sfr     45eh
-
-
-; Port pin name definitions.
-
-a4d0    bit     P0.0
-a5d1    bit     P0.1
-a6d2    bit     P0.2
-a7d3    bit     P0.3
-a8d4    bit     P0.4
-a9d5    bit     P0.5
-a10d6   bit     P0.6
-a11d7   bit     P0.7
-
-a0      bit     P1.0
-wrh     bit     P1.0
-a1      bit     P1.1
-a2      bit     P1.2
-a3      bit     P1.3
-rxd1    bit     P1.4
-txd1    bit     P1.5
-t2      bit     P1.6
-t2ex    bit     P1.7
-
-a12d8   bit     P2.0
-a13d9   bit     P2.1
-a14d10  bit     P2.2
-a15d11  bit     P2.3
-a16d12  bit     P2.4
-a17d13  bit     P2.5
-a18d14  bit     P2.6
-a19d15  bit     P2.7
-
-rxd0    bit     P3.0
-txd0    bit     P3.1
-int0    bit     P3.2
-int1    bit     P3.3
-t0      bit     P3.4
-t1      bit     P3.5
-busw    bit     P3.5
-wrl     bit     P3.6
-rd      bit     P3.7
-
-; End of XA-G3 SFR definitions.
-;$list         ;handle this later on
-
-
-
-
-trap_delay             equ             0
-trap_cout              equ             1
-
-       org             $8040           ;paulmon2 will jump here on trap #0
-       jmp             syscall_sleep
-       org             $8044           ;paulmon2 will jump here on trap #1
-       jmp             syscall_cout
-
-       org             $8084           ;paulmon2 will jump here on timer0 interrupt
-       jmp             timer0
-
-       org             $80A0           ;paulmon2 will jump here on uart0 rx interrupt
-       jmp             uart0_recv
-       org             $80A4           ;paulmon2 will jump here on uart0 tx interrupt
-       jmp             uart0_xmit
-       org             $80A8           ;paulmon2 will jump here on uart1 rx interrupt
-       jmp             uart1_recv
-       org             $80AC           ;paulmon2 will jump here on uart1 tx interrupt
-       jmp             uart1_xmit
-
-       org             $8100           ;paulmon2 will jump here on software int1
-       jmp             context_switch
-       org             $8104           ;paulmon2 will jump here on software int2
-       jmp             do_events
-
-       org             $8120
-       jmp             poweron
-
-request_do_events                      bit             swr2
-request_context_switch         bit             swr1
-
-max_num_ticks  equ             7               ;max time a process can run if other
-                                                               ;processes are waiting in the run queue
-
-
-;this memory allocation should be done with "ds" directives to
-;save space, but for now it's done with "equ" with lots of gaps,
-;so that things will stay put and aligned on 16 byte boundries
-;where they can be easily viewed with the paulmon2 hex dump.  When
-;the kernel code is more mature this will have to be changed.
-
-sys_stack              equ             $FB00
-
-rx0_buf_head   equ             $FB00           ;2 bytes
-rx0_buf_tail   equ             $FB02           ;2 bytes
-rx0_buf_size   equ             $20
-rx0_buf                        equ             $FB10           ;rx0_buf_size bytes
-
-rx1_buf_head   equ             $FB40           ;2 bytes
-rx1_buf_tail   equ             $FB42           ;2 bytes
-rx1_buf_size   equ             $20
-rx1_buf                        equ             $FB50           ;rx1_buf_size bytes
-
-tx0_buf_head   equ             $FB80           ;2 bytes
-tx0_buf_tail   equ             $FB82           ;2 bytes
-tx0_buf_size   equ             $20
-tx0_buf_threshold      equ     9
-tx0_buf                        equ             $FB90           ;tx0_buf_size bytes
-
-tx1_buf_head   equ             $FBC0           ;2 bytes
-tx1_buf_tail   equ             $FBC2           ;2 bytes
-tx1_buf_size   equ             $20
-tx1_buf_threshold      equ     9
-tx1_buf                        equ             $FBD0           ;tx1_buf_size bytes
-
-
-current_proc   equ             $FEF0   ;2 bytes, ptr to proc_table entry of
-                                                               ;currently running process, 0 if none
-run_queue              equ             $FEF2   ;2 bytes, pointer to a linked list
-                                                               ;of processes waiting to run
-sleep_queue            equ             $FEF4   ;2 bytes, pointer to a linked list
-                                                               ;of sleeping processes
-time_running   equ             $FEF6   ;1 byte, number of ticks that the
-                                                               ;current process has run.
-event_queue            equ             $FCF0   ;2 bytes, pointer to a linked list
-                                                               ;of pending events (event_table)
-
-max_num_proc   equ             14
-proc_table             equ             $FE00   ;(max_num_proc*pt_entry_size) bytes
-pt_entry_size  equ             16              ;16 bytes per table entry
-pt_usp                 equ             0               ;2 bytes, User Stack Pointer
-pt_q_next              equ             2               ;2 bytes, ptr to next in queue
-pt_q_prev              equ             4               ;2 bytes, ptr to prev in queue (+pt_q_next)
-pt_wait                        equ             6               ;2 bytes, what are we waiting for?
-pt_wakeup              equ             8               ;2 bytes, where do we go on wakeup?
-pt_prog_addr   equ             10              ;2 bytes, location of program header
-pt_prog_cs             equ             12              ;1 byte, code segment of program header
-pt_priority            equ             13              ;1 byte, execution priority
-pt_pid                 equ             14              ;1 byte, id num for this process
-
-       ;need to define a program header, which will include various
-       ;info about the program, including the req'd stack space, max
-       ;expect memory to malloc, range of directly addressed memory
-       ;(which must be saved during a context switch), max number of
-       ;open file descriptors reqd, etc.
-
-max_num_event  equ             15              ;(max_num_proc*2)
-event_table            equ             $FC00   ;(max_num_event*evt_entry_size)
-evt_entry_size equ             16              ;8 bytes per event entry
-evt_ticks              equ             0               ;# of ticks until event (delta from prev)
-evt_next               equ             2               ;pointer to next event in list
-evt_function   equ             4               ;place to call (0 if evt slot unused)
-evt_arg1               equ             6               ;optional argument
-
-;the file descriptors will be allocated before the stack in the
-;block of memory which is allocated when the process is created.
-;each individual process can specify the max number of file
-;descriptors that it will require
-
-file_desc_table        equ             $FE80   ;128 bytes
-fd_entry_size  equ             7               ;7 bytes per table entry
-fd_offset              equ             0               ;4 bytes, offset in file
-fd_flags               equ             4               ;1 byte, read/write/append
-fd_routines            equ             5               ;2 bytes, ptr to i/o routines
-
-
-;single character debug symbols:
-;  space       context switcher is idle
-;    *      contect switcher entered
-;    #         timer interrupt (normal)
-;    %         timer interrupt requested context switch
-;    !      timer interrupt requested event service
-;       @              entered event service interrupt routine
-;    ^         event service function called
-;       ~      leaving event service interrupt routine
-
-;this timer interrupt routine is responsible for monitoring the
-;time that the current process has been running and adjusting the
-;process priorities accordingly.  It also checks if any events
-;in the event queue need to be processed.  This code runs at a
-;high cpu priority and it runs often, so it should get done as
-;quickly as possible... if anything lengthy might need to be done,
-;a software interrupt (low priority) should be set, so it can be
-;done later on without blocking other important interrupts, such
-;as low-level i/o.
-
-timer0:
-       push    r0, r1, r2, r3, r4, r5, r6
-       ;other stuff can be added here, such as maintaining a
-       ;system clock...
-         ;mov  r4l, #'#'
-check_events:
-       mov             r0, #event_queue
-       clr             ea
-       mov             r1, [r0]
-       beq             ckevt_end               ;no events if queue is empty
-       mov             r2, [r1+evt_ticks]
-       beq             ckevt_do_em
-       ;if we get here, there are events pending but it's not
-       ;time to do any of them yet, so we'll just decrement the
-       ;ticks of the first one, which will decrement the effective
-       ;time for all of them since they use a delta-time between
-       ;each entry in the linked list
-       adds.w  [r1+evt_ticks], #-1
-       br              ckevt_end
-ckevt_do_em:
-       ;if we get here, there is at least one event which needs
-       ;to be serviced... but we won't do that here, just set the
-       ;software interrupt so it can be handled by "do_event"
-       ;setb   request_do_events
-         ;mov  r4l, #'!'
-         ;call cout
-       ;call   do_events               ;not nice, but sw int priority not working
-       setb    request_do_events
-ckevt_end:
-       setb    ea
-       nop
-schedule:
-       mov             r0, #current_proc
-       clr             ea
-       mov             r1, [r0]
-       beq             sch_end                 ;don't bother if no process is running
-       sub.b   [r1+pt_priority], #1    ;decrease priority by one
-       bcc     sch_priority_ok
-       movs.b  [r1+pt_priority], #0    ;but don't go less than zero
-sch_priority_ok:
-       mov             r0, #time_running
-       mov             r3l, [r0]
-       adds    r3l, #1                         ;increment time_running
-       mov             [r0], r3l
-       cmp             r3l, #max_num_ticks
-       bl              sch_end
-       ;if we get here, the currently running process is has been
-       ;using the cpu for at least the max number ticks, so it's
-       ;time to force it to take a rest and let someone else have
-       ;a chance.
-       mov             r0, #run_queue
-       mov             r1, [r0]
-       beq             sch_end         ;don't preempt if nothing in run queue
-         ;mov  r4l, #'%'
-       setb    request_context_switch          ;make something else run
-sch_end:
-       setb    ea
-         ;cmp  r4l, #'!'
-         ;beq  t0_skip_print
-         ;call cout
-       nop
-t0_skip_print:
-       pop             r0, r1, r2, r3, r4, r5, r6
-       reti
-
-
-       ;this routine actually calls the event handlers for all
-       ;events which are supposed to happen NOW.  The main timer
-       ;routine must decrement the time of the events and arrange
-       ;for this code to be run when any events are supposed to
-       ;happen.  The event handler gets the address of the event
-       ;in r1.
-do_events:
-       push    r0, r1, r2, r3, r4, r5, r6
-do_events_begin:
-         ;mov  r4l, #'@'
-         ;call cout
-doevt_loop:
-       mov             r0, #event_queue
-       mov             r1, [r0]
-       beq             doevt_end               ;no events to do if queue is empty
-       mov             r2, [r1+evt_ticks]
-       bne             doevt_end               ;done if event is in the future
-       mov             r2, [r1+evt_next]
-       mov             [r0], r2                ;remove event from queue
-       mov             r2, [r1+evt_function]
-       movs.w  [r1+evt_function], #0
-         ;mov  r4l, #'^'
-         ;call cout
-       call    [r2]                    ;call the event handler specified
-       br              doevt_loop
-doevt_end:
-         ;mov  r4l, #'~'
-         ;call cout
-       clr             request_do_events
-       pop             r0, r1, r2, r3, r4, r5, r6
-       reti
-
-
-
-;interrupt receive routine for uart #0
-uart0_recv:
-       push    r0, r1, r2, r5, r6
-       clr             ri_0
-       mov             r5l, s0buf
-       mov             r2, #rx0_buf
-       mov             r0, #rx0_buf_head
-       mov             r6, #rx0_buf_tail
-       mov             r1, [r0]
-       adds    r1, #1
-       cjne    r1, #rx0_buf+rx0_buf_size, uart_recv_check2
-       mov             r1, #rx0_buf
-       br              uart_recv_check2
-;interrupt receive routine for uart #1
-uart1_recv:
-       push    r0, r1, r2, r5, r6
-       clr             ri_1
-       mov             r5l, s1buf
-       mov             r2, #rx1_buf
-       mov             r0, #rx1_buf_head
-       mov             r6, #rx1_buf_tail
-       mov             r1, [r0]
-       adds    r1, #1
-       cjne    r1, #rx1_buf+rx1_buf_size, uart_recv_check2
-       mov             r1, #rx1_buf
-;this remaining code is shared by both uart receive routines
-uart_recv_check2:
-       cmp             r1, [r6]
-       bne             uart_recv_ok
-       ;if we get here, the buffer is full, discard data
-       call    wakeup_intr_io
-       pop             r0, r1, r2, r5, r6
-       reti
-uart_recv_ok:
-       mov.b   [r1], r5l               ;store byte into buffer
-       mov             [r0], r1                ;update buffer pointer
-       ;perhaps there should be a way for us to know how much data a
-       ;sleeping process wants to extract from the buffer, so we can
-       ;avoid waking it up until there is at least that much data.
-       call    wakeup_intr_io
-       pop             r0, r1, r2, r5, r6
-       reti
-
-;interrupt transmit routine for uart #0
-uart0_xmit:
-       push    r0, r1, r2, r5, r6
-       clr             ti_0
-       mov             r0, #tx0_buf_tail
-       mov             r2, #tx0_buf_head
-       mov             r1, [r0]
-       cmp             r1, [r2]
-       beq             uart_no_xmit
-       adds    r1, #1
-       cjne    r1, #tx0_buf+tx0_buf_size, uart0_xmit2
-       mov             r1, #tx0_buf
-uart0_xmit2:
-       mov.b   s0buf, [r1]
-       mov             [r0], r1
-       ;now figure out if we want to wake up processes which are
-       ;waiting to put more data into this buffer
-       mov             r1, [r2]
-       sub             r1, [r0]
-       bcc             uart0_xmit3
-       add             r1, #tx0_buf_size
-uart0_xmit3:
-       cmp             r1, #(tx0_buf_threshold)
-       bcc             uart0_xmit_end          ;don't wake proc unless over threshold
-       mov             r2, #tx0_buf
-       call    wakeup_intr_io
-uart0_xmit_end:
-       pop             r0, r1, r2, r5, r6
-       reti
-;interrupt transmit routine for uart #1
-uart1_xmit:
-       push    r0, r1, r2, r5, r6
-       clr             ti_1
-       mov             r0, #tx1_buf_tail
-       mov             r2, #tx1_buf_head
-       mov             r1, [r0]
-       cmp             r1, [r2]
-       beq             uart_no_xmit
-       adds    r1, #1
-       cjne    r1, #tx1_buf+tx1_buf_size, uart1_xmit2
-       mov             r1, #tx1_buf
-uart1_xmit2:
-       mov.b   s1buf, [r1]
-       mov             [r0], r1
-       ;now figure out if we want to wake up processes which are
-       ;waiting to put more data into this buffer
-       mov             r1, [r2]
-       sub             r1, [r0]
-       bcc             uart1_xmit3
-       add             r1, #tx1_buf_size
-uart1_xmit3:
-       cmp             r1, #tx1_buf_threshold
-       bcc             uart1_xmit_end          ;don't wake proc unless over threshold
-       mov             r2, #tx1_buf
-       call    wakeup_intr_io
-uart1_xmit_end:
-       pop             r0, r1, r2, r5, r6
-       reti
-
-;this is shared by both transmit interrupt routines
-uart_no_xmit:
-       ;if we got here, there is no data waiting to transmit
-       ;load the _head pointer with 0, so a routine which loads
-       ;data into the buffer will know to set the ti bit.
-       movs.w  [r2], #0
-       pop             r0, r1, r2, r5, r6
-       reti
-
-
-;This routine wakes up any sleeping processes that are waiting
-;for i/o in the buffer pointed to by r2.  Interrupt routines
-;should call here after doing i/o one their buffers, so that
-;any processes which are waiting for that i/o will be awakened.
-
-wakeup_intr_io:
-       mov             r0, #sleep_queue
-       mov             r1, [r0]
-       beq             wkintio_empty   ;sleep_queue is empty
-       clr             ea                      ;disable interrupts while we look at the queue
-wkintio_loop:
-       cmp             [r1+pt_wait], r2
-       beq             wkintio_wakeup  ;wake proc if waiting for i/o on this buffer
-       mov             r1, [r1+pt_q_next]
-       bne             wkintio_loop
-       setb    ea                              ;ok for other interrupts now
-wkintio_empty:
-       ret
-wkintio_wakeup:
-       ;if we get here, this sleeping processes was waiting for
-       ;i/o on the buffer pointed to by r2, so let's wake it up.
-       ;d_que_proc: (remove from sleep queue)
-       mov             r6, [r1+pt_q_next]
-       push    r6                                              ;save ptr to next in sleep queue
-       mov             r5, [r1+pt_q_prev]
-       mov             [r5], r6
-       mov             [r6+pt_q_prev], r5
-       ;en_que_proc: (add to run queue)
-       mov             r0, #run_queue
-       mov             [r1+pt_q_prev], r0
-       mov             r5, [r0]
-       mov             [r1+pt_q_next], r5
-       lea             r6, r1+pt_q_next
-       mov             [r5+pt_q_prev], r6
-       mov             [r0], r1
-       adds.b  [r1+pt_priority], #5    ;give it a bit of priority boost...
-       ;need to check here for overrange on user priority
-       setb    request_context_switch  ;get it running asap.
-       ;continue looking for processes waiting on this i/o buffer,
-       ;because there may be more than one, and we need to get them
-       ;all into the run queue so that the context switcher can choose
-       ;the one with the highest priority.
-       pop             r1
-       cmp             r1, #0
-       bne             wkintio_loop
-       setb    ea
-       ret
-
-
-
-
-
-
-
-;**************************************************************
-
-
-
-
-
-
-;The context switcher is responsible for figuring out which process
-;is supposed to run next (looks at pt_priority) and if a context
-;change is required this is where it will happen.  If any
-;interrupt driven part of the kernel wants to make a particular
-;process run, it must change the priority for that process and
-;then set the software interrupt to run the context switcher later.
-
-;For system calls that want to make their calling process sleep,
-;they should jump to the ksleep routine, which will jump to
-;"ctsw_begin" to allow something else to run.
-
-;Note: the context switcher doesn't enforce preemptive multitasking...
-;a timer routine must count how long the currently running process
-;has be running since a context switch ("time_running" variable)
-;and if it's being a hog the timer routine that detects it must
-;lower the priority and set the software interrupt to cause this
-;context switcher to make a different process run.  The context
-;switcher also depends on interrupt routines to change the
-;"pt_priority" field of each process table entry, all the context
-;switcher does is pick the process with highest priority.  The
-;currently running process is always switched out if there is
-;something in the run queue, even if the item in the run queue
-;has a lower priority.
-
-
-context_switch:
-       pushu   r0, r1, r2, r3, r4, r5, r6              ;save registers
-       pop             r2, r3, r4                                              ;get pc and psw
-       pushu   r2, r3, r4                                              ;save them on user stack
-       pushu.b ds
-       pushu.b es
-       pushu.b ssel
-
-
-ctsw_begin:
-         ;mov  r4l, #'*'
-         ;call cout
-ctsw_retry:
-       ;find the process on the run queue with highest priority
-       mov             r0, #run_queue
-       mov             r1, [r0]
-       beq             ctsw_queue_empty        ;run_queue is empty
-       movs    r2, #0                  ;r2 is proc w/ highest priority
-       mov             r3l, #0                 ;r3l is highest priority we've seen
-       clr             ea                      ;disable interrupts while we look at the
-                                               ;run queue, since interrupt routines will be
-                                               ;changing priorities to influence which process
-                                               ;should be run next
-ctsw_loop:
-       cmp             [r1+pt_priority], r3l
-       bcs             ctsw_skip
-       ;if we get here, this process is the highest
-       ;priority so far, so forget about any other
-       mov             r3l, [r1+pt_priority]
-       mov             r2, r1
-ctsw_skip:
-       mov             r1, [r1+pt_q_next]
-       bne             ctsw_loop
-       ;now r2 points to the process which should be running...
-       ;check to see if "current_proc" is valid... if it is zero then
-       ;nothing was running (a sys call probably put the process to
-       ;sleep).  If "current_proc" has a valid process pointer, then we
-       ;need to save that process's context (apart from the pushed regs)
-       ;and put that process back into the run queue
-       mov             r0, #current_proc
-       mov             r1, [r0]
-       beq             ctsw_switch
-       call    save_context
-       movs.w  [r1+pt_wakeup], #0              ;wants to go back to user mode
-       mov             r0, #run_queue
-       call    en_que_proc                             ;put back into run queue
-ctsw_switch:
-       ;now it's time to switch to the new process that is about
-       ;to start running.
-       mov             r1, r2
-       call    d_que_proc                      ;remove new proc from run queue
-       call    restore_context
-       mov             r0, #time_running
-       movs.b  [r0], #0                        ;reset "time_running"
-       mov             r0, #current_proc
-       mov             [r0], r1                        ;set "current_proc" to new process
-       ;we may need to return to executing the process in user mode,
-       ;or we may need to jump to a location in the kernel (to continue
-       ;a system call).  If pt_wakup for this process is not zero, then
-       ;some kernel routine caused this process to sleep or be preempted
-       ;and wants to do more work before finally returning to the user
-       ;mode and running the program again.  Usually this is due to a
-       ;system call which needed to put the process to sleep while
-       ;waiting for I/O.
-       mov             r6, [r1+pt_wakeup]
-       setb    ea
-       beq             ctsw_return
-       movs.w  [r1+pt_wakeup], #0      ;don't do this again unless set again
-       jmp             [r6]
-ctsw_return:
-       clr             request_context_switch
-       popu.b  ssel
-       popu.b  es
-       popu.b  ds
-       popu    r2, r3, r4
-    push       r2, r3, r4
-       popu    r0, r1, r2, r3, r4, r5, r6
-       reti
-
-ctsw_queue_empty:
-       ;if we get here, there was no process waiting in the run
-       ;queue.  However, the currently running process isn't
-       ;normally in the run queue, so check if there was a process
-       ;running... if so reset its time slice and let it continue
-       mov             r0, #current_proc
-       mov             r1, [r0]
-       beq             ctsw_idle               ;idle if nothing was running
-       mov             r0, #time_running
-       movs.b  [r0], #0
-       jmp             ctsw_return
-       ;if we get here, the run queue is empty and there in no
-       ;process running now, so we just keep looping inside the
-       ;context switcher until something appears in the run queue
-ctsw_idle:
-       ;need to make a special user-mode idle process... someday
-       ;that could put the processor into idle-mode to save power
-         ;mov  r4l, #' '
-         ;call cout
-       jmp             ctsw_retry
-
-
-
-
-;This "ksleep" routine causes the current process to sleep, afterwhich
-;it jumps to the context switcher, which tries to pick something else to
-;run, if anything is ready.  This code should only be called from
-;within the service code of system calls, which often times need to
-;make their calling process sleep.  R3 should have a value to stuff
-;into "pt_wait" for the process.  ksleep should be CALLed, because
-;it will arrange for the scheduler to return back to the kernel code
-;which called ksleep.  The call to ksleep should be followed by a
-;single NOP, for jump alignment.  Note, before calling ksleep some mechanism
-;to wake the sleeping process back up again must be in place... there
-;is nothing within ksleep which arranges for the process to become
-;awake again, though in the case of i/o the value in r3 should cause it
-;to wake up of the i/o interrupt routine checks for that value.
-
-ksleep:
-       clr             ea
-       mov             r0, #current_proc
-       mov             r1, [r0]                                ;get pointer to process
-         ;cmp  r1, #$FE10
-         ;beq  ksleep_die
-       movs.w  [r0], #0                                ;no current process anymore
-       nop
-ksleep_any:
-       clr             ea
-       mov             [r1+pt_wait], r3                ;record what we're waiting for
-       pop             r5, r6                                  ;get return address
-       adds    r6, #1                                  ;make sure return addr is word addr
-       and             r6, #$FFFE
-       mov             [r1+pt_wakeup], r6              ;set return addr when it wakes up
-       adds.b  [r1+pt_priority], #3    ;increase priority a bit
-       ;need to check here for overrange on user priority
-       mov             r0, #sleep_queue
-       call    en_que_proc                     ;add it to the sleep queue
-       setb    ea
-       call    save_context
-         ;cmp  r1, #$FE10
-         ;beq  ksleep_die
-       jmp             ctsw_begin                              ;scheduler will pick a new
-                                                                       ;process to run (or run idle loop)
-
-ksleep_die:
-       jmp             die
-
-
-syscall_sleep:
-       ;all system calls should run at the same priority as the
-       ;context switcher (level #1), but the code in paulmon2
-       ;sets the trap priority to #8... need to change that.
-       mov.b           pswh, #10000001q
-       pushu   r0, r1, r2, r3, r4, r5, r6              ;save registers
-       pop             r4, r5, r6                                              ;get pc and psw
-       pushu   r4, r5, r6                                              ;save them on user stack
-       pushu.b ds
-       pushu.b es
-       pushu.b ssel
-       ;r0 is number of ticks to sleep, from caller
-       mov             r4, #wake_process
-       mov             r2, #current_proc
-       mov             r5, [r2]        ;"wake_process" will need to know which proc
-       call    add_event
-       mov             r3, #0          ;no other routines will need to know it's sleeping
-       call    ksleep
-       nop
-       popu.b  ssel
-       popu.b  es
-       popu.b  ds
-       popu    r2, r3, r4
-    push       r2, r3, r4
-       popu    r0, r1, r2, r3, r4, r5, r6
-       reti
-
-       ;do_events is supposed to call here when the process is supposed
-       ;to wake up again... all we have to do it remove the process
-       ;from the sleep queue, add it to the run queue, and set the
-       ;software interrupt for the context switcher so it will select
-       ;a new process to run, and it will likely be this one since we
-       ;gave the priority a boost when it was put to sleep.
-       nop
-wake_process:
-         ;mov  r4l, #'$'
-         ;call cout
-       ;r1 should point to event table entry created earlier
-       clr             ea
-       mov             r1, [r1+evt_arg1]       ;now r1 points to process entry
-       call    d_que_proc                      ;remove it from the sleep queue
-       mov             r0, #run_queue
-       call    en_que_proc                     ;add it to the run queue
-       setb    ea
-       ;should really test the priority of this waking process and
-       ;the priority of the currently running one, and only do the
-       ;context switch if the waking one has a higher priority
-       setb    request_context_switch
-       ret
-
-
-
-
-       ;transmit the character in r4l
-syscall_cout:
-       mov.b           pswh, #10000001q
-       pushu   r0, r1, r2, r3, r4, r5, r6              ;save registers
-       pop             r3, r5, r6                                              ;get pc and psw
-       pushu   r3, r5, r6                                              ;save them on user stack
-       pushu.b ds
-       pushu.b es
-       pushu.b ssel
-sc_cout_begin:
-       mov             r0, #tx0_buf_head
-       mov             r2, #tx0_buf_tail
-       clr             ea
-       mov             r1, [r0]
-       bne             sc_cout2
-       ;if we get here, the transmit buffer is empty and the interrupt
-       ;routine cleared the ti bit so no more interrupts are expected
-       setb    ti_0                    ;give the transmitter a kick-start
-       mov             r1, #tx0_buf
-       mov             [r0], r1                ;restore buffer pointers to useful values
-       mov             [r2], r1
-sc_cout2:
-       adds    r1, #1
-       cjne    r1, #tx0_buf+tx0_buf_size, sc_cout3
-       mov             r1, #tx0_buf
-sc_cout3:
-       cmp             r1, [r2]
-       bne             sc_cout4
-       ;if we get here, the buffer is full, so let's just wait
-       ;in a loop... eventually this routine will be replaced
-       ;with "write" which will put the process to sleep and set
-       ;the pt_wait so the context switcher will return here when
-       ;there is space available.  How do we save the variables
-       ;associated with the system call??  Push them onto the
-       ;user's stack for this process?
-       setb    ea
-       mov             r3, #tx0_buf
-       pushu   r4
-       call    ksleep
-       nop
-       popu    r4
-       br              sc_cout_begin   ;try again now that the intr i/o woke us up
-sc_cout4:
-       mov.b   [r1], r4l               ;put data into buffer
-       mov             [r0], r1                ;update pointer
-       setb    ea
-       popu.b  ssel
-       popu.b  es
-       popu.b  ds
-       popu    r2, r3, r4
-    push       r2, r3, r4
-       popu    r0, r1, r2, r3, r4, r5, r6
-       reti
-
-
-
-
-
-
-
-
-       ;this function adds an event to the event queue.  These
-       ;parameters are required:
-       ;       r0      number of ticks until the event should occur
-       ;       r4      function to call when event happens (not zero!!)
-       ;       r5      optional argument
-       ;the event list uses delta time between each entry, so that
-       ;the timer interrupt will only have to deal with the front
-       ;of the queue... but it makes adding an entry here much more
-       ;difficult, but we only have to do this once whereas the
-       ;timer will have to look at the queue however many times the
-       ;evt_ticks value specifies.
-add_event:
-       ;the first thing to do is find a empty place in the table
-       ;to store this event
-       mov             r1, #event_table
-       mov             r2, #max_num_event
-       clr             ea
-aevt_find_slot:
-       mov             r3, [r1+evt_function]
-       beq             aevt_found_slot
-       add             r1, #evt_entry_size
-       djnz    r2, aevt_find_slot
-       ;if we get here there were no slots available, which is a
-       ;very bad thing...
-       jmp             kernel_panic
-aevt_found_slot:
-       ;now that we've located the slot we'll use, let's dump the
-       ;data into it before making a mistake and reusing one of the
-       ;registers that are holding the input parameters
-       mov             [r1+evt_ticks], r0              ;store time value
-       mov             [r1+evt_function], r4   ;store function to be called
-       mov             [r1+evt_arg1], r5               ;store argument
-       ;now we've got to add this event into the linked list in
-       ;the correct time sequence position, and also subtract the
-       ;sum of all the previous evt_ticks values from this one.
-       mov             r6, #event_queue
-       mov             r2, [r6]
-       bne             aevt_check_first
-       ;if we get here, it's easy because the list is empty...
-       mov             [r6], r1
-       movs.w  [r1+evt_next], #0
-       setb    ea
-       ret
-aevt_check_first:
-       ;it may be the case that our new event is supposed to happen
-       ;before the events that are already on the queue
-       cmp             r0, [r2+evt_ticks]
-       bcc             aevt_search
-       mov             [r6], r1
-       mov             [r1+evt_next], r2
-aevt_adjust:
-       ;now that we've added an entry (at r1), we need to adjust the
-       ;evt_ticks values stored in the entry that comes after it.
-       mov             r3, [r1+evt_next]               ;r3 points to next event after ours
-       mov             r4, [r1+evt_ticks]
-       sub             [r3+evt_ticks], r4
-       setb    ea
-       ret
-aevt_search:
-       ;r4 is the adjusted value of ticks for our event as we progress
-       ;through the linked list
-       mov             r4, [r1+evt_ticks]
-aevt_search_loop:
-    sub                r4, [r2+evt_ticks]
-       mov             r3, [r2+evt_next]
-       beq             aevt_add
-       cmp             r4, [r3+evt_ticks]
-       bcs             aevt_add
-       mov             r2, r3
-       jmp             aevt_search_loop
-aevt_add:
-       ;r2 points to the event before the place where we will add
-       ;and r3 points to the place after it in the list
-       mov             [r2+evt_next], r1
-       mov             [r1+evt_next], r3
-       mov             [r1+evt_ticks], r4
-       bne             aevt_adjust                             ;adjust rest of list if it exists
-       setb    ea
-       ret
-
-
-
-
-save_context:          ;process pointer in r1
-       mov             r0, usp
-       mov             [r1+pt_usp], r0                 ;save user stack pointer
-       ;save any directly addressed memory range
-       ;assigned to this process
-       ret
-
-restore_context:               ;process pointer in r1
-       mov             r0, [r1+pt_usp]
-       mov             usp, r0                         ;restore usp to value for new process
-       ;copy contents of directly addresses memory
-       ;back if necessary
-       ret
-
-
-
-
-;This routine removes a process (at r1) from a process queue
-;(run/sleep).  This might be better as an assembler macro, but
-;it's in a subroutine because of the difficulty of figuring out
-;how to correctly manipulate the pointers of a doubly-linked list
-d_que_proc:
-       mov             r6, [r1+pt_q_next]              ;<-- should be macro (begin)
-       mov             r5, [r1+pt_q_prev]
-       mov             [r5], r6
-       mov             [r6+pt_q_prev], r5              ;<--- should be macro (end)
-       ret
-
-;this routine takes a process (at r1) and adds it to a queue, where
-;the location of the head of the queue is in r0.  This is more or
-;less the opposite of "d_que_proc" except that the new process is
-;always added to the head of the list.
-en_que_proc:
-       mov             [r1+pt_q_prev], r0              ;<-- should be macro (begin)
-       mov             r5, [r0]
-       mov             [r1+pt_q_next], r5
-       lea             r6, r1+pt_q_next
-       mov             [r5+pt_q_prev], r6
-       mov             [r0], r1                                ;<--- should be macro (end)
-       ret
-
-;pt_usp                        equ             0               ;2 bytes, User Stack Pointer
-;pt_q_next             equ             2               ;2 bytes, ptr to next in queue
-;pt_q_prev             equ             4               ;2 bytes, ptr to prev in queue (+pt_q_next)
-
-
-;this routine creates a new process, and returns a pointer to it
-;in r1.  If the process can't be created, r1 is zero.  Data about
-;the new process is required:
-;      r4 = location of executable program
-;      r5 = location for user stack (eventually malloc will do this)
-
-
-create_process:
-       mov             r1, #proc_table
-       mov             r2, #max_num_proc
-cproc_find_slot:
-       mov             r0, [r1+pt_usp]
-       beq             cproc_found_slot                ;ok to use this process entry
-       add             r1, #pt_entry_size
-       djnz    r2, cproc_find_slot
-       ;if we get here, there is no more room in the process
-       ;table so we can't create a new process.
-       movs    r1, #0
-       ret
-cproc_found_slot:
-       push    r4, r5
-       ;first initialize the various kernel data required
-       mov             r0, #run_queue
-       clr             ea
-       call    en_que_proc                                     ;add it to the run queue
-       mov.b   [r1+pt_priority], #100          ;start at priority 100
-       movs.w  [r1+pt_wait], #0
-       movs.w  [r1+pt_wakeup], #0
-       ;next we need to set up the process's context
-       pop             r4, r5
-       sub             r5, #26                         ;advance r5 to context storage area
-       mov             [r1+pt_usp], r5
-       movs.w  [r5+], #0                       ;segment select is 0
-       movs.w  [r5+], #0                       ;es is 0
-       movs.w  [r5+], #0                       ;ds is 0
-       movs.w  [r5+], #0                       ;psw is zero (user mode)
-       movs.w  [r5+], #0                       ;run is page zero only (for now)
-       mov             [r5+], r4                       ;set return addr to beginning
-       ;could create initial values for the registers here...
-       setb    ea
-       ret
-
-;user stack while in kernel mode:
-; byte
-; offset   Variable
-;      -2              r6
-;      -4              r5
-;      -6              r4
-;      -8              r3
-;      -10             r2
-;      -12             r1
-;      -14             r0
-;      -16             program counter (lsw)
-;      -18             program counter (msb)
-;      -20             program status word
-;      -22             ds
-;      -24             es
-;      -26             ssel            <-- usp points here
-
-
-poweron:
-       mov             r6, #$F000
-clear_memory_loop:
-       movs.w  [r6+], #0
-       cjne    r6, #0, clear_memory_loop
-         setb  p1.6
-         setb  p1.7
-
-       mov             r7, #sys_stack                          ;set sys stack pointer
-       clr             ea
-       ;initialize serial port buffers
-       mov             r0, #rx0_buf_head
-       mov.w   [r0], #rx0_buf
-       mov             r0, #rx0_buf_tail
-       mov.w   [r0], #rx0_buf
-       mov             r0, #tx0_buf_head
-       movs.w  [r0], #0
-       mov             r0, #tx0_buf_tail
-       movs.w  [r0], #0
-       mov             r0, #rx1_buf_head
-       mov.w   [r0], #rx1_buf
-       mov             r0, #rx1_buf_tail
-       mov.w   [r0], #rx1_buf
-       mov             r0, #tx1_buf_head
-       movs.w  [r0], #0
-       mov             r0, #tx1_buf_tail
-       movs.w  [r0], #0
-       ;clear serial port flags
-       clr             ri_0
-       clr             ti_0
-       clr             ri_1
-       clr             ti_1
-       ;initialize interrupts
-       mov.b   swe, #255                               ;allow all software interrupts
-    mov.b   ipa0, #10010000q           ;priority #9: timer0 interrupt
-       mov.b   ipa4, #10011001q                ;priority #9: uart0 rx and tx interrupts
-       mov.b   ipa5, #10011001q                ;priority #9: uart1 rx and tx interrupts
-       mov.b   ieh, #00001111q                 ;enable uart interrupts
-       ;set up timer 0 to 16-bit auto reload (10 ms)
-       clr             et0                                             ;no timer 0 interrupt yet
-       clr             tr0                                             ;stop timer 0
-       clr             tf0
-       mov.b   rtl0, #low 37798                ;set 10 ms rate
-       mov.b   rth0, #high 37798
-       movs.b  tl0, #0                                 ;zero timer
-       movs.b  th0, #0
-       and.b   tmod, #11110000q                ;set for 16 bit auto reload
-
-
-    ;now set up the variables so we're in idle mode
-       mov             r0, #current_proc
-       movs.w  [r0], #0                                        ;set no process running
-       mov             r0, #run_queue
-       movs.b  [r0], #0                                        ;all queues empty
-       mov             r0, #sleep_queue
-       movs.b  [r0], #0
-       mov             r0, #time_running
-       movs.b  [r0], #0
-       ;initialize pt_usp of all processes to zero, so that
-       ;there won't appear to be any processes
-
-       nop
-clr_proc_tbl:
-       mov             r1, #proc_table
-       mov             r2, #max_num_proc
-clr_proc_tbl_loop:
-       movs.w  [r1+pt_usp], #0
-       add             r1, #pt_entry_size
-       djnz    r2, clr_proc_tbl_loop
-clr_events:
-       mov             r1, #event_table
-       mov             r2, #max_num_event
-clr_events_loop:
-       movs.w  [r1+evt_function], #0
-       add             r1, #evt_entry_size
-       djnz    r2, clr_events_loop
-
-;now create process table entries for the test programs
-       mov             r4, #program1
-       mov             r5, #$F000
-       call    create_process          ;create process for program1
-       mov             r4, #program2
-       mov             r5, #$EC00
-       call    create_process          ;create process for program2
-       mov             r4, #program3
-       mov             r5, #$E800
-       ;call   create_process          ;create process for program3
-
-
-
-       ;now how can we get into user mode for the first time???
-       ;normally the kernel is entered by an interrupt (hardware
-       ;or software) or a trap (sys call), so we get back to a
-       ;user program with reti... but the first time has to be
-       ;handled a bit differently
-       mov             r1, #proc_table
-       call    d_que_proc                      ;remove new proc to run from run queue
-       call    restore_context
-       mov             r0, #time_running
-       movs.b  [r0], #0                        ;reset "time_running"
-       mov             r0, #current_proc
-       mov             [r0], r1                        ;set "current_proc" to new process
-       popu.b  ssel
-       popu.b  es
-       popu.b  ds
-       popu    r0, r1, r2                      ;r0=psw, r1=pc_high, r2=pc_low
-       popu    r3, r4, r5                      ;extract r0/r2 reg from stack
-       popu    r3, r4, r5, r6          ;extract r3/r6 reg from stack
-       mov             cs, r1l                         ;set code segment
-       clr             tf0                                     ;clear timer0 flag
-       setb    tr0                                     ;start timer0
-       setb    et0                                     ;enable timer0 interrupt
-       setb    ea
-       mov             pswl, r0l
-       mov             pswh, r0h                       ;this makes the switch to user mode
-                                                               ;and lower priority to 0 (from max)
-       jmp             [r2]                            ;jump to the user program
-
-
-
-
-kernel_panic:
-die:
-       clr             ea
-       clr             ri_0
-die_loop:
-       jnb             ri_0, die_loop
-       clr             ri_0
-       jmp             $120            ;reboot!
-
-
-
-;unix system calls: (which ones to try first??)
-;process mgt: fork, exec/execve, exit, wait/wait4
-;file i/o: open, read, write, select, ioclt, lseek, close, fcntl
-;signals: kill, signal, alarm, pause
-;pipes: pipe, dup/dup2
-;network/ipc: socket, bind, connect/listen/accept, sendto, recvfrom
-;network/ipc: socketpair, getsockname/getpeername, setsockopt/getsockopt
-;filesystems: chroot/chdir, link, unlink, mkdir, rmdir,
-;filesystems: chown/chmod, stat, rename, truncate
-
-
-
-
-;**************************************************************
-;**                                                          **
-;**                     User Programs                        **
-;**                                                          **
-;**************************************************************
-
-
-
-cout:
-       trap    #trap_cout
-       ret
-
-newline:
-       push    r4l
-       mov             r4l, #13
-       call    cout
-       mov             r4l, #10
-       call    cout
-       pop             r4l
-       ret
-
-pstr:      PUSH    r4
-pstr1:     MOVC    r4l,[r6+]
-           beq     pstr2
-           AND     R4L,#0x7F
-           CALL    cout
-           BR      pstr1
-pstr2:     POP     r4
-           RET
-
-phex:
-phex8:
-           PUSH.B  acc
-           RL.B R4L,#4
-           AND.B   R4L,#15
-           ADD.B   R4L,#246
-           BCC     phex_b
-           ADD.B   R4L,#7
-phex_b:    ADD.B   R4L,#58
-           CALL    cout
-           POP.B   acc
-phex1:     PUSH.B  acc
-           AND.B   R4L,#15
-           ADD.B   R4L,#246
-           BCC     phex_c
-           ADD.B   R4L,#7
-phex_c:    ADD.B   R4L,#58
-           CALL    cout
-           POP.B   acc
-           RET
-
-phex16:
-           PUSH.B  acc
-           MOV.B   R4L,dph
-           CALL    phex
-           MOV.B   R4L,dpl
-           CALL    phex
-           POP.B   acc
-           RET
-
-
-
-
-
-       ;program #1 prints "Paul" to serial port #0, with a
-       ;fairly long delay between each printing
-program1:
-       mov             r6, #str_paul
-       call    pstr
-       mov             r0, #130
-       trap    #trap_delay
-       jmp             program1
-
-str_paul: db "Paul",0
-
-pgm2_speed             equ             10              ;number of ticks between led blinks
-
-       nop
-       ;program #2 blinks the LEDs and prints a "." to the
-       ;serial port #0 after every sequence of blinks.
-program2:
-       or.b    p1cfga, #$C0                    ;p1.6 and p1.7 outputs
-       or.b    p1cfgb, #$C0
-pg2_loop:
-       ;br             pg2_skip_blink
-       setb    p1.6
-       setb    p1.7
-       mov             r0, #pgm2_speed
-       trap    #trap_delay
-       clr             p1.6
-       setb    p1.7
-       mov             r0, #pgm2_speed
-       trap    #trap_delay
-       setb    p1.6
-       setb    p1.7
-       mov             r0, #pgm2_speed
-       trap    #trap_delay
-       setb    p1.6
-       clr             p1.7
-       mov             r0, #pgm2_speed
-       trap    #trap_delay
-       setb    p1.6
-       setb    p1.7
-
-pg2_skip_blink:
-       mov             r4l, #'.'
-       call    cout
-       br              pg2_loop
-
-program3:
-       mov             r4l, #'3'
-       call    cout
-       ;mov            r6, #test_str
-       ;call   pstr
-       jmp             program3
-
-
-test_str: db "This_is_a_test", 0
-
-
-
-
-
-
-
-
-
diff --git a/as/xa51/paulmon2.xa b/as/xa51/paulmon2.xa
deleted file mode 100644 (file)
index 6d26aba..0000000
+++ /dev/null
@@ -1,1941 +0,0 @@
-; this copy is hacked to write to page 0Fxxxx when receiving
-; an intel-hex download... so it hopefully work on Matt's
-; 16-bit board layout.
-
-;$pagewidth 132t
-
-; This is a hacked copy of paulmon2 which is intended to work
-; with the XA processor.  Automatic baud rate detection is not
-; supported, and the extras package is not avaialble.  Flash
-; ROM is not supported.  Paulmon2 only understands the first 64k
-; of memory, and only recognizes intel-hex with 64k address
-; space.  Due to differences in arrangement of the XA, Paulmon2
-; may crash if it receives invalid intel-hex code (untested).
-; See comments in "dnld_ghex" for details about this.
-
-; Other bugs may exist, but the system seems to work.
-
-; Paulmon2 does NOT run in the XA's special 8051 compatibility
-; mode.  Paulmon2 shuts off the watchdog timer and runs all
-; code in system mode (highest priority).
-
-;$include xa-g3.equ
-
-acc     reg     R4L
-dpl     reg     R6L
-dph     reg     R6H
-s0con   sfr     420h
-ri_0    bit     s0con.0
-ti_0    bit     s0con.1
-pswl    sfr     400h
-psw51   sfr     402h
-tcon    sfr     410h
-tr1     bit     tcon.6
-s0buf   sfr     460h
-wdcon   sfr     41fh
-wfeed1  sfr     45dh
-wfeed2  sfr     45eh
-tl1     sfr     452h
-tmod    sfr     45ch
-rtl1    sfr     456h
-ssel   sfr     403h
-cs     sfr     443h
-
-
-; PAULMON2, a user-friendly 8051 monitor, by Paul Stoffregen
-; Please email comments, suggestions, bugs to paul@ece.orst.edu
-
-; It's free.  You may copy sections of code from PAULMON2
-; into your own programs, even for commercial purposes.
-; PAULMON2 should only be distributed free of charge, but may
-; be bundled as 'value-added' with other products, such as
-; development boards, CDROMs, etc.  Please distribute the
-; PAULMON2.DOC file and other files, not just the object code!
-
-; The PAULMON2.EQU and PAULMON2.HDR files contain valuable
-; information that could help you to write programs for use
-; with PAULMON2.
-
-; PAULMON2 is in the public domain. PAULMON2 is distributed in
-; the hope that it will be useful, but without any warranty;
-; without even the implied warranty of merchantability or fitness
-; for a particular purpose.
-
-
-carry  bit     pswl.7
-flag0  bit     psw51.5
-flag1  bit     psw51.1
-
-;---------------------------------------------------------;
-;                                                         ;
-;           PAULMON2's default configuration              ;
-;                                                         ;
-;---------------------------------------------------------;
-
-; PAULMON2 should be assembled using the modified AS31 assembler,
-; originally written by Ken Stauffer, many small changes by Paul
-; Stoffregen.  This free assembler is available on the web at
-; http://www.ece.orst.edu/~paul/8051-goodies/goodies-index.html
-; As well, these web pages have a fill-out form which makes it
-; very easy to custom configure PAULMON2.  Using this form will
-; edit the code for you, run the AS31 assmebler, and send you the
-; object code to program into your chip.
-
-
-vector         equ     $8000
-
-; These three parameters tell PAULMON2 where the user's memory is
-; installed.  "bmem" and "emem" define the space that will be searched
-; for program headers, user installed commands, start-up programs, etc.
-; "bmem" and "emem" should be use so they exclude memory areas where
-; perphreal devices may be mapped, as reading memory from an io chip
-; may reconfigure it unexpectedly.  If flash rom is used, "bmem" and "emem"
-; should also include the space where the flash rom is mapped.
-
-pgm        EQU     $F000            ;default location for the user program
-bmem       EQU     $0000            ;where is the beginning of memory
-emem       EQU     $FFFF            ;end of the memory
-
-
-; Please note... much of the memory management code only looks at the
-; upper 8 bits of an address, so it's not a good idea to somehow map
-; your memory chips (with complex address decoding logic) into chunks
-; less than 256 bytes.  In other words, only using a piece of a flash
-; rom chip and mapping it between C43A to F91B would confuse PAULMON2
-; (as well as require quit a bit of address decoding logic circuitry)
-
-; To set the baud rate, use this formula or set to 0 for auto detection
-; baud_const = 256 - (crystal / (4 * 16 * baud))  <-- for XA chip
-
-;baud_const EQU                247             ;19200 baud w/ 11.0592 MHz (XA)
-;baud_const EQU                253             ;57600 baud w/ 11.0592 MHz (XA)
-baud_const EQU         251             ;57600 baud w/ 18.432 MHz (XA)
-;baud_const EQU                241             ;19200 baud w/ 18.432 MHz (XA)
-;baud_const EQU                236             ;19531 baud w/ 25 MHz (XA)
-
-
-; About download speed: when writing to ram, PAULMON2 can accept data
-; at the maximum baud rate (baud_const=255 or 57600 baud w/ 11.0592 MHz).
-; Most terminal emulation programs introduce intentional delays when
-; sending ascii data, which you would want to turn off for downloading
-; larger programs into ram.  For Flash ROM, the maximum speed is set by
-; the time it takes to program each location... 9600 baud seems to work
-; nicely for the AMD 28F256 chip.  The "character pacing" delay in a
-; terminal emulation program should be sufficient to download to flash
-; rom and any baud rate.
-
-
-; Several people didn't like the key definations in PAULMON1.
-; Actually, I didn't like 'em either, but I never took the time
-; to change it.  Eventually I got used to them, but now it's
-; really easy to change which keys do what in PAULMON2.  You
-; can guess what to do below, but don't use lowercase.
-
-help_key   EQU     '?'              ;help screen
-dir_key    EQU     'M'              ;directory
-run_key    EQU     'R'              ;run program
-dnld_key   EQU     'D'              ;download
-upld_key   EQU     'U'              ;upload
-nloc_key   EQU     'N'              ;new memory location
-jump_key   EQU     'J'              ;jump to memory location
-dump_key   EQU     'H'              ;hex dump memory
-intm_key   EQU     'I'              ;hex dump internal memory
-edit_key   EQU     'E'              ;edit memory
-clrm_key   EQU     'C'              ;clear memory
-erfr_key   EQU     'Z'              ;erase flash rom
-xdump_key  EQU     'X'              ;hex dump ext data memory
-
-
-;location of parameter table used by download command
-;sixteen bytes of internal memory are required beginning at this
-;location
-
-dnld_parm  EQU     $01F0
-stack      EQU     $01EE
-
-;---------------------------------------------------------;
-;                                                         ;
-;                    Interrupt Vectors                    ;
-;  (and little bits of code crammed in the empty spaces)  ;
-;                                                         ;
-;---------------------------------------------------------;
-
-           ORG     0
-
-                       dw      $8f00, poweron
-breakvec:      dw      $8f00, vector + breakvec
-tracevec:      dw      $8f00, vector + tracevec
-stackovvec:    dw      $8f00, vector + stackovvec
-div0vec:       dw      $8f00, vector + div0vec
-uretivec:      dw      $8f00, vector + uretivec
-                       org     $40
-trap0vec:      dw      $8800, vector + trap0vec
-trap1vec:      dw      $8800, vector + trap1vec
-trap2vec:      dw      $8800, vector + trap2vec
-trap3vec:      dw      $8800, vector + trap3vec
-trap4vec:      dw      $8800, vector + trap4vec
-trap5vec:      dw      $8800, vector + trap5vec
-trap6vec:      dw      $8800, vector + trap6vec
-trap7vec:      dw      $8800, vector + trap7vec
-trap8vec:      dw      $8800, vector + trap8vec
-trap9vec:      dw      $8800, vector + trap9vec
-trap10vec:     dw      $8800, vector + trap10vec
-trap11vec:     dw      $8800, vector + trap11vec
-trap12vec:     dw      $8800, vector + trap12vec
-trap13vec:     dw      $8800, vector + trap13vec
-trap14vec:     dw      $8800, vector + trap14vec
-trap15vec:     dw      $8800, vector + trap15vec
-                       org     $80
-int0vec:       dw      $8900, vector + int0vec
-tmr0vec:       dw      $8900, vector + tmr0vec
-int1vec:       dw      $8900, vector + int1vec
-tmr1vec:       dw      $8900, vector + tmr1vec
-tmr2vec:       dw      $8900, vector + tmr2vec
-                       org     $A0
-rxd0vec:       dw      $8900, vector + rxd0vec
-txd0vec:       dw      $8900, vector + txd0vec
-rxd1vec:       dw      $8900, vector + rxd1vec
-txd1vec:       dw      $8900, vector + txd1vec
-                       org     $100
-swi1vec:       dw      $8100, vector + swi1vec
-swi2vec:       dw      $8200, vector + swi2vec
-swi3vec:       dw      $8300, vector + swi3vec
-swi4vec:       dw      $8400, vector + swi4vec
-swi5vec:       dw      $8500, vector + swi5vec
-swi6vec:       dw      $8600, vector + swi6vec
-swi7vec:       dw      $8700, vector + swi7vec
-
-          org     $120
-
-               jmp             poweron
-
-
-space:     MOV.B   R4L,#' '
-           CALL    cout
-           RET
-
-dash:      MOV.B   R4L,#'-'
-           CALL    cout
-           RET
-
-
-;---------------------------------------------------------;
-;                                                         ;
-;       The jump table for user programs to call          ;
-;             subroutines within PAULMON                  ;
-;                                                         ;
-;---------------------------------------------------------;
-
-; no jump table anymore... use TRAP or conditional assembly.
-
-
-;---------------------------------------------------------;
-;                                                         ;
-;              Subroutines for serial I/O                 ;
-;                                                         ;
-;---------------------------------------------------------;
-
-
-;these are the only three routines which access the serial port directly
-;but poweron/autobaud to the initial setup
-
-cin:       JNB     ri_0,cin
-           CLR     ri_0
-           MOV.B   R4L,s0buf
-           RET
-cout:      JNB     ti_0,cout
-           CLR     ti_0               ;clr ti before the mov to sbuf!
-           MOV.B   s0buf,R4L
-           RET
-esc:  ;checks to see if <ESC> is waiting on serial port
-      ;C=clear if no <ESC>, C=set if <ESC> pressed
-      ;buffer is flushed
-           PUSH.B  acc
-           CLR     carry
-           JNB     ri_0,esc2
-          clr     ri_0
-           MOV.B   R4L, s0buf
-           CJNE.B  R4L,#27,esc2
-           SETB    carry
-esc2:      POP.B   acc
-           RET
-
-
-;everything else from here on should only access the serial
-;port using cin/cout/etc
-
-
-newline:   PUSH.B  acc
-           MOV.B   R4L,#13
-           CALL    cout
-           MOV.B   R4L,#10
-           CALL    cout
-           POP.B   acc
-           RET
-
-       ;get 2 digit hex number from serial port
-       ; c = set if ESC pressed, clear otherwise
-       ; flag0 = set if return w/ no input, clear otherwise
-ghex:
-ghex8:     CLR     flag0
-ghex8c:
-           CALL    cin              ;get first digit
-           CALL    upper
-           CJNE.B  R4L,#27,ghex8f
-ghex8d:    SETB    carry
-           MOVS    R4L,#0
-           RET
-ghex8f:    CJNE.B  R4L,#13,ghex8h
-           SETB    flag0
-           CLR     carry
-           MOVS    R4L,#0
-           RET
-ghex8h:    MOV.B   R1L,R4L
-           CALL    asc2hex
-           BCS     ghex8c
-           XCH.B   R4L,R1L          ;r2 will hold hex value of 1st digit
-           CALL    cout
-ghex8j:
-           CALL    cin              ;get second digit
-           CALL    upper
-           CJNE.B  R4L,#27,ghex8k
-           BR      ghex8d
-ghex8k:    CJNE.B  R4L,#13,ghex8m
-           MOV.B   R4L,R1L
-           CLR     carry
-           RET
-ghex8m:    CJNE.B  R4L,#8,ghex8p
-ghex8n:    CALL    cout
-           BR      ghex8c
-ghex8p:    CJNE.B  R4L,#21,ghex8q
-           BR      ghex8n
-ghex8q:    MOV.B   R1H,R4L
-           CALL    asc2hex
-           BCS     ghex8j
-           XCH.B   R4L,R1H
-           CALL    cout
-           MOV.B   R4L,R1L
-           RL.B R4L,#4
-           OR.B    R4L,R1H
-           CLR     carry
-           RET
-
-
-
-
-       ;carry set if esc pressed
-       ;flag0 set if return pressed w/ no input
-ghex16:
-           MOV.B   R1L,#0           ;start out with 0
-           MOV.B   R1H,#0
-           MOV.B   R2L,#4           ;number of digits left
-           CLR     flag0
-
-ghex16c:
-           CALL    cin
-           CALL    upper
-           CJNE.B  R4L,#27,ghex16d
-           SETB    carry            ;handle esc key
-           MOVS    R4L,#0
-           MOV.B   dph,R4L
-           MOV.B   dpl,R4L
-           RET
-ghex16d:   CJNE.B  R4L,#8,ghex16f
-           BR      ghex16k
-ghex16f:   CJNE.B  R4L,#127,ghex16g ;handle backspace
-ghex16k:   CJNE.B  R2L,#4,ghex16e   ;have they entered anything yet?
-           BR      ghex16c
-ghex16e:   CALL    cout
-           CALL    ghex16y
-           ADDS.B  R2L,#1
-           BR      ghex16c
-ghex16g:   CJNE.B  R4L,#13,ghex16i  ;return key
-           MOV.B   dph,R1H
-           MOV.B   dpl,R1L
-           CJNE.B  R2L,#4,ghex16h
-           MOVS    R4L,#0
-           MOV.B   dph,R4L
-           MOV.B   dpl,R4L
-           SETB    flag0
-ghex16h:   CLR     carry
-           RET
-ghex16i:   MOV.B   R2H,R4L          ;keep copy of original keystroke
-           CALL    asc2hex
-           BCS     ghex16c
-           XCH.B   R4L,R2H
-           CALL    cout
-           MOV.B   R4L,R2H
-           PUSH.B  acc
-           CALL    ghex16x
-           POP.B   acc
-           ADD.B   R4L,R1L
-           MOV.B   R1L,R4L
-           MOVS    R4L,#0
-           ADDC.B  R4L,R1H
-           MOV.B   R1H,R4L
-           DJNZ.B  R2L,ghex16c
-           CLR     carry
-           MOV.B   dpl,R1L
-           MOV.B   dph,R1H
-           RET
-
-ghex16x:  ;multiply r3-r2 by 16 (shift left by 4)
-           MOV.B   R4L,R1H
-           RL.B R4L,#4
-           AND.B   R4L,#11110000Q
-           MOV.B   R1H,R4L
-           MOV.B   R4L,R1L
-           RL.B R4L,#4
-           AND.B   R4L,#00001111Q
-           OR.B    R4L,R1H
-           MOV.B   R1H,R4L
-           MOV.B   R4L,R1L
-           RL.B R4L,#4
-           AND.B   R4L,#11110000Q
-           MOV.B   R1L,R4L
-           RET
-
-ghex16y:  ;divide r3-r2 by 16 (shift right by 4)
-           MOV.B   R4L,R1L
-           RL.B R4L,#4
-           AND.B   R4L,#00001111Q
-           MOV.B   R1L,R4L
-           MOV.B   R4L,R1H
-           RL.B R4L,#4
-           AND.B   R4L,#11110000Q
-           OR.B    R4L,R1L
-           MOV.B   R1L,R4L
-           MOV.B   R4L,R1H
-           RL.B R4L,#4
-           AND.B   R4L,#00001111Q
-           MOV.B   R1H,R4L
-           RET
-
-asc2hex:             ;carry set if invalid input
-           CLR     carry
-           PUSH.B  R4H
-           SUBB.B  R4L,#'0'
-           MOV.B   R4H,R4L
-           SUBB.B  R4L,#10
-           BCS     a2h1
-           MOV.B   R4L,R4H
-           SUBB.B  R4L,#7
-           MOV.B   R4H,R4L
-a2h1:      MOV.B   R4L,R4H
-           CLR     carry
-           AND.B   R4L,#11110000Q   ;just in case
-           JZ      a2h2
-           SETB    carry
-a2h2:      MOV.B   R4L,R4H
-           POP.B   R4H
-           RET
-
-
-phex:
-phex8:
-           PUSH.B  acc
-           RL.B R4L,#4
-           AND.B   R4L,#15
-           ADD.B   R4L,#246
-           BCC     phex_b
-           ADD.B   R4L,#7
-phex_b:    ADD.B   R4L,#58
-           CALL    cout
-           POP.B   acc
-phex1:     PUSH.B  acc
-           AND.B   R4L,#15
-           ADD.B   R4L,#246
-           BCC     phex_c
-           ADD.B   R4L,#7
-phex_c:    ADD.B   R4L,#58
-           CALL    cout
-           POP.B   acc
-           RET
-
-
-phex16:
-           PUSH.B  acc
-           MOV.B   R4L,dph
-           CALL    phex
-           MOV.B   R4L,dpl
-           CALL    phex
-           POP.B   acc
-           RET
-
-
-;a not so well documented feature of pstr is that you can print
-;multiple consecutive strings without needing to reload dptr
-;(which takes 3 bytes of code!)... this is useful for inserting
-;numbers or spaces between strings.
-
-pstr:      PUSH.B  acc
-pstr1:     MOVS    R4L,#0
-           MOVC.B  A,[A+dptr]
-           ADDS.W  R6,#1
-           JZ      pstr2
-           MOV     C,R4L.7
-           AND.B   R4L,#0x7F
-           CALL    cout
-           BCS     pstr2
-           BR      pstr1
-pstr2:     POP.B   acc
-           RET
-
-
-
-;---------------------------------------------------------;
-;                                                         ;
-;    The 'high-level' stuff to interact with the user     ;
-;                                                         ;
-;---------------------------------------------------------;
-
-
-menu: ;first we print out the prompt
-           MOV.W   R6,#prompt1      ;give 'em the first part of prompt
-           CALL    pcstr
-           MOV.B   R4L,R3H
-           CALL    phex
-           MOV.B   R4L,R3L
-           CALL    phex
-           CALL    space
-       MOV.W   R6,#prompt2
-           CALL    pstr
-
-
-;now we're past the prompt, so let's get some input
-           CALL    cin              ;get the input
-           CALL    upper
-
-
-menu1a:    CJNE.B  R4L,#help_key,menu1b
-           MOV.W   R6,#help_cmd2
-           CALL    pcstr
-           call     help
-               jmp     menu
-menu1b:    CJNE.B  R4L,#dir_key,menu1c
-           MOV.W   R6,#dir_cmd
-           CALL    pcstr
-           call     dir
-               jmp     menu
-menu1c:    CJNE.B  R4L,#run_key,menu1d
-           MOV.W   R6,#run_cmd
-           CALL    pcstr
-           call        run
-               jmp     menu
-menu1d:    CJNE.B  R4L,#dnld_key,menu1e
-           MOV.W   R6,#dnld_cmd
-           CALL    pcstr
-           call     dnld
-               jmp             menu
-menu1e:    CJNE.B  R4L,#upld_key,menu1f
-           MOV.W   R6,#upld_cmd
-           CALL    pcstr
-           call     upld
-               jmp             menu
-menu1f:    CJNE.B  R4L,#nloc_key,menu1g
-           MOV.W   R6,#nloc_cmd
-           CALL    pcstr
-           call     nloc
-               jmp             menu
-menu1g:    CJNE.B  R4L,#jump_key,menu1h
-           MOV.W   R6,#jump_cmd
-           CALL    pcstr
-           call        jump
-               jmp             menu
-menu1h:    CJNE.B  R4L,#dump_key,menu1i
-           MOV.W   R6,#dump_cmd
-           CALL    pcstr
-           call        dump
-               jmp             menu
-menu1i:    CJNE.B  R4L,#edit_key,menu1j
-           MOV.W   R6,#edit_cmd
-           CALL    pcstr
-           call        edit
-               jmp             menu
-menu1j:    CJNE.B  R4L,#clrm_key,menu1l
-           MOV.W   R6,#clrm_cmd
-           CALL    pcstr
-           call   clrm
-               jmp             menu
-menu1l:    CJNE.B  R4L,#intm_key,menu1m
-           MOV.W   R6,#intm_cmd
-           CALL    pcstr
-           call        intm
-               jmp             menu
-menu1m:    CJNE.B  R4L,#xdump_key,menu1n
-           MOV.W   R6,#xdump_cmd
-           CALL    pcstr
-           call        xdump
-               jmp             menu
-menu1n:
-
-    ;invalid input, no commands to run...
-menu_end:                       ;at this point, we have not found
-           CALL    newline          ;anything to run, so we give up.
-               jmp             menu
-
-;..........................................................
-
-;---------------------------------------------------------;
-
-;dnlds1 = "Begin sending Intel HEX format file <ESC> to abort"
-;dnlds2 = "Download aborted"
-;dnlds3 = "Download completed"
-
-
-;16 byte parameter table: (eight 16 bit values)
-;  *   0 = lines received
-;  *   1 = bytes received
-;  *   2 = bytes written
-;  *   3 = bytes unable to write
-;  *   4 = incorrect checksums
-;  *   5 = unexpected begin of line
-;  *   6 = unexpected hex digits (while waiting for bol)
-;  *   7 = unexpected non-hex digits (in middle of a line)
-
-dnld:
-           MOV.W   R6,#dnlds1
-           CALL    pcstr          ;"begin sending file <ESC> to abort"
-       mov.w   r5,#dnld_parm
-        mov.b   R1L,#8
-dnld0:  movs.w  [r5+],#0          ;initialize all parameters to 0
-        DJNZ.B  R1L,dnld0
-
-         ;look for begining of line marker ':'
-dnld1:     CALL    cin
-           CJNE.B  R4L,#27,dnld2    ;Test for escape
-           BR      dnld_esc
-dnld2:     CJNE.B  R4L,#':',dnld2b
-       mov.w   r5, #dnld_parm
-       adds.w  [r5+0], #1
-           BR      dnld3
-dnld2b:   ;check to see if it's a hex digit, error if it is
-           CALL    asc2hex
-           BCS     dnld1
-        mov.w   r5, #dnld_parm
-        adds.w  [r5+12], #1
-           BR      dnld1
-         ;begin taking in the line of data
-dnld3:     MOV.B   R4L,#'.'
-           CALL    cout
-           MOV.B   R2L,#0           ;r4 will count up checksum
-           CALL    dnld_ghex
-           MOV.B   R0L,R4L          ;R0 = # of data bytes
-           MOV.B   R2L,R4L
-           CALL    dnld_ghex
-           MOV.B   dph,R4L          ;High byte of load address
-           ADD.B   R4L,R2L
-           MOV.B   R2L,R4L
-           CALL    dnld_ghex
-           MOV.B   dpl,R4L          ;Low byte of load address
-           ADD.B   R4L,R2L
-           MOV.B   R2L,R4L
-           CALL    dnld_ghex        ;Record type
-           MOV.B   R1L,R4L
-           ADD.B   R4L,R2L
-           MOV.B   R2L,R4L
-           MOV.B   R4L,R1L
-           CJNE.B  R4L,#1,dnld4     ;End record?
-           BR      dnld_end
-dnld4:
-dnld5:     CALL    dnld_ghex        ;Get data byte
-           MOV.B   R1L,R4L
-        mov.w   r5, #dnld_parm
-        adds.w  [r5+2], #1
-           MOV.B   R4L,R1L
-           ADD.B   R4L,R2L
-           MOV.B   R2L,R4L
-           MOV.B   R4L,R1L
-           CALL    smart_wr         ;c=1 if an error writing
-           MOVS    R4L,#0
-           ADDC.B  R4L,#2
-           MOV.B   R0H,R4L
-;     2 = bytes written
-;     3 = bytes unable to write
-       rl.b    r4l, #1
-       movs.b  r4h, #0
-       mov.w   r5, #dnld_parm
-       add.w   r5, r4
-       adds.w  [r5], #1
-
-           ADDS.W  R6,#1
-           DJNZ.B  R0L,dnld5
-
-           CALL    dnld_ghex        ;get checksum
-           ADD.B   R4L,R2L
-           JZ      dnld1            ;should always add to zero
-dnld_sumerr:
-        mov.w   r5, #dnld_parm
-        adds.w  [r5+8], #1
-           BR      dnld1
-
-dnld_end:   ;handles the proper end-of-download marker
-           CALL    dnld_ghex        ;get the last checksum
-       ;assume no data in this line.
-           ADD.B   R4L,R2L
-           JNZ     dnld_sumerr
-           CALL    dnld_dly
-           MOV.W   R6,#dnlds3
-           CALL    pcstr          ;"download went ok..."
-       ;consume any cr or lf character that may have been
-       ;on the end of the last line
-           JNB     ri_0,dnld_sum
-           CALL    cin
-           BR      dnld_sum
-
-dnld_esc:   ;handle esc received in the download stream
-           CALL    dnld_dly
-           MOV.W   R6,#dnlds2
-           CALL    pcstr          ;"download aborted."
-           BR      dnld_sum
-
-dnld_dly:   ;a short delay since most terminal emulation programs
-           ;won't be ready to receive anything immediately after
-           ;they've transmitted a file... even on a fast Pentium(tm)
-           ;machine with 16550 uarts!
-           MOV.B   R0L,#0
-dnlddly2:  MOV.B   R0H,#0
-dnlddly3:  DJNZ.B  R0H,dnlddly3       ;roughly 128k cycles, appox 0.1 sec
-           DJNZ.B  R0L,dnlddly2
-           RET
-
-
-
-
-
-
-;a special version of ghex just for the download.  Does not
-;look for carriage return or backspace.  Handles ESC key by
-;poping the return address (I know, nasty, but it saves many
-;bytes of code in this 4k ROM) and then jumps to the esc
-;key handling.  This ghex doesn't echo characters, and if it
-;sees ':', it pops the return and jumps to an error handler
-;for ':' in the middle of a line.  Non-hex digits also jump
-;to error handlers, depending on which digit.
-
-; XA compatibility issue: This code pops the return address
-; off the stack and does a jump to an error handler.  The
-; code should examine the mode bit to see if return addresses
-; are 16 or 32 bits on the stack.  As it is, it will probably
-; work in non 16-bit mode (default), but this code could
-; use some attention to this detail nonetheless.
-
-dnld_ghex:
-dnldgh1:   CALL    cin
-           CALL    upper
-           CJNE.B  R4L,#27,dnldgh3
-dnldgh2:   POP.B   acc                 ;<-- compatibility problem!!!  Check XA mode
-           POP.B   acc                 ;<-- and pop correct number of words off stack
-           BR      dnld_esc
-dnldgh3:   CJNE.B  R4L,#':',dnldgh5
-dnldgh4:
-        mov.w   r5, #dnld_parm
-        adds.w  [r5+10], #1    ;handle unexpected beginning of line
-           POP.B   acc                 ;<-- compatibility problem!!!  Check XA mode
-           POP.B   acc                 ;<-- and pop correct number of words off stack
-           JMP     dnld3            ;and now we're on a new line!
-dnldgh5:   CALL    asc2hex
-           BCC     dnldgh6
-        mov.w   r5, #dnld_parm
-        adds.w  [r5+14], #1
-           BR      dnldgh1
-dnldgh6:   MOV.B   R1L,R4L          ;keep first digit in r2
-dnldgh7:   CALL    cin
-           CALL    upper
-           CJNE.B  R4L,#27,dnldgh8
-           BR      dnldgh2
-dnldgh8:   CJNE.B  R4L,#':',dnldgh9
-           BR      dnldgh4
-dnldgh9:   CALL    asc2hex
-           BCC     dnldghA
-        mov.w   r5, #dnld_parm
-        adds.w  [r5+14], #1
-           BR      dnldgh7
-dnldghA:   XCH.B   R4L,R1L
-           RL.B R4L,#4
-           OR.B    R4L,R1L
-           RET
-
-;dnlds4 =  "Summary:"
-;dnlds5 =  " lines received"
-;dnlds6a = " bytes received"
-;dnlds6b = " bytes written"
-
-dnld_sum:    ;print out download summary
-           MOV.W   R6,#dnlds4
-           CALL    pcstr
-        MOV.w   r5, #dnld_parm
-       mov.w   r6, [r5+]
-           CALL    space
-           CALL    pint16u
-           MOV.W   R6,#dnlds5
-           CALL    pcstr
-       mov.w   r6, [r5+]
-           CALL    space
-           CALL    pint16u
-           MOV.W   R6,#dnlds6a
-           CALL    pcstr
-       mov.w   r6, [r5+]
-           CALL    space
-           CALL    pint16u
-           MOV.W   R6,#dnlds6b
-           CALL    pcstr
-dnld_err:    ;now print out error summary
-           MOV.w   r5, #dnld_parm + 6
-                       mov     r1l, #5
-dnlder2:
-               mov.w   r6, [r5+]
-           bne     dnlder3          ;any errors?
-           DJNZ.B  R1L,dnlder2
-        ;no errors, so we print the nice message
-           MOV.W   R6,#dnlds13
-           CALL    pcstr
-           RET
-dnlder3:  ;there were errors, so now we print 'em
-           MOV.W   R6,#dnlds7
-           CALL    pcstr
-         ;but let's not be nasty... only print if necessary
-               mov             r5, #dnld_parm+6
-               mov             r6, [r5+]
-        beq     dnlder4
-           CALL    space
-           CALL    pint16u
-           MOV.W   R6,#dnlds8
-           CALL    pcstr
-dnlder4:
-               mov             r6, [r5+]
-               beq             dnlder5
-           CALL    space
-           CALL    pint16u
-           MOV.W   R6,#dnlds9
-           CALL    pcstr
-dnlder5:
-               mov             r6, [r5+]
-        beq     dnlder6
-           CALL    space
-           CALL    pint16u
-           MOV.W   R6,#dnlds10
-           CALL    pcstr
-dnlder6:
-        mov     r6, [r5+]
-        beq     dnlder7
-           CALL    space
-           CALL    pint16u
-           MOV.W   R6,#dnlds11
-           CALL    pcstr
-dnlder7:
-        mov     r6, [r5+]
-        beq     dnlder8
-           CALL    space
-           CALL    pint16u
-           MOV.W   R6,#dnlds12
-           CALL    pcstr
-dnlder8:   CALL    newline
-           RET
-
-;dnlds7:  = "Errors:"
-;dnlds8:  = " bytes unable to write"
-;dnlds9:  = " incorrect checksums"
-;dnlds10: = " unexpected begin of line"
-;dnlds11: = " unexpected hex digits"
-;dnlds12: = " unexpected non-hex digits"
-;dnlds13: = "No errors detected"
-
-
-
-;---------------------------------------------------------;
-
-
-jump:
-           MOV.W   R6,#prompt8
-           CALL    pcstr
-       mov.w   r6, r3
-           CALL    phex16
-           MOV.W   R6,#prompt4
-           CALL    pcstr
-           CALL    ghex16
-           JB      flag0,jump3
-           BCC     jump2
-           MOV.W   R6,#abort
-           CALL    pcstr
-           CALL    newline
-           RET
-jump2:         mov.w   r3, r6
-jump3:     CALL    newline
-           MOV.W   R6,#runs1
-           CALL    pcstr
-                       mov.w   r6, r3
-                       call    phex16
-                       call    newline
-                       mov.w   r6, r3
-
-jump_doit:  ;jump to user code @dptr (this used by run command also)
-       movs.w  r0, #0
-       push.w  r0
-       mov.w  r0, #$120
-       push.w  r0
-       jmp     [r6]
-
-
-;---------------------------------------------------------;
-
-dump:
-           MOV.B   R1L,#16          ;number of lines to print
-           CALL    newline
-           CALL    newline
-dump1:
-       push    r6
-       mov     r6, #msg_code
-       call    pstr
-       pop     r6
-          MOV.B   dpl,R3L
-           MOV.B   dph,R3H
-           CALL    phex16           ;tell 'em the memory location
-           MOV.B   R4L,#':'
-           CALL    cout
-           CALL    space
-           MOV.B   R1H,#16          ;r3 counts # of bytes to print
-           MOV.B   dpl,R3L
-           MOV.B   dph,R3H
-dump2:     MOVS    R4L,#0
-           MOVC.B  A,[A+dptr]
-           ADDS.W  R6,#1
-           CALL    phex             ;print each byte in hex
-           CALL    space
-           DJNZ.B  R1H,dump2
-           CALL    space            ;print a couple extra space
-           CALL    space
-           MOV.B   R1H,#16
-           MOV.B   dpl,R3L
-           MOV.B   dph,R3H
-dump3:     MOVS    R4L,#0
-           MOVC.B  A,[A+dptr]
-           ADDS.W  R6,#1
-           AND.B   R4L,#01111111Q   ;avoid unprintable characters
-           CLR     carry
-           SUBB.B  R4L,#20h
-           BCC     dump4            ;avoid control characters
-           MOV.B   R4L,#(' ' - 20h)
-dump4:     ADD.B   R4L,#20h
-           CALL    cout
-           DJNZ.B  R1H,dump3
-           CALL    newline
-           MOV.B   R3L,dpl
-           MOV.B   R3H,dph
-           CALL    esc
-           BCS     dump5
-           DJNZ.B  R1L,dump1        ;loop back up to print next line
-dump5:     CALL    newline
-           RET
-
-msg_code: db "Code:",0
-msg_xram: db "Xram:",0
-
-;---------------------------------------------------------;
-
-
-xdump:
-           MOV.B   R1L,#16          ;number of lines to print
-           CALL    newline
-           CALL    newline
-xdump1:        
-       push    r6
-       mov     r6, #msg_xram
-       call    pstr
-       pop     r6
-       MOV.B   dpl,R3L
-           MOV.B   dph,R3H
-           CALL    phex16           ;tell 'em the memory location
-           MOV.B   R4L,#':'
-           CALL    cout
-           CALL    space
-           MOV.B   R1H,#16          ;r3 counts # of bytes to print
-           MOV.B   dpl,R3L
-           MOV.B   dph,R3H
-xdump2:    MOVS    R4L,#0
-           MOVX                  r4l,[r6]
-           ADDS.W  R6,#1
-           CALL    phex             ;print each byte in hex
-           CALL    space
-           DJNZ.B  R1H,xdump2
-           CALL    space            ;print a couple extra space
-           CALL    space
-           MOV.B   R1H,#16
-           MOV.B   dpl,R3L
-           MOV.B   dph,R3H
-xdump3:    MOVS    R4L,#0
-           MOVX                  r4l,[r6]
-           ADDS.W  R6,#1
-           AND.B   R4L,#01111111Q   ;avoid unprintable characters
-           CLR     carry
-           SUBB.B  R4L,#20h
-           BCC     xdump4            ;avoid control characters
-           MOV.B   R4L,#(' ' - 20h)
-xdump4:    ADD.B   R4L,#20h
-           CALL    cout
-           DJNZ.B  R1H,xdump3
-           CALL    newline
-           MOV.B   R3L,dpl
-           MOV.B   R3H,dph
-           CALL    esc
-           BCS     xdump5
-           DJNZ.B  R1L,xdump1        ;loop back up to print next line
-xdump5:    CALL    newline
-           RET
-
-
-
-
-;---------------------------------------------------------;
-
-nloc:
-           MOV.W   R6,#prompt6
-           CALL    pcstr
-           CALL    ghex16
-           BCS     nloc2
-           JB      flag0,nloc2
-           MOV.B   R3L,dpl
-           MOV.B   R3H,dph
-           CALL    newline
-           CALL    newline
-           RET
-nloc2:     MOV.W   R6,#abort
-           CALL    pcstr
-           CALL    newline
-           RET
-
-;---------------------------------------------------------;
-
-
-edit:      ;edit external ram...
-           MOV.W   R6,#edits1
-           CALL    pcstr
-           MOV.B   dpl,R3L
-           MOV.B   dph,R3H
-edit1:     CALL    phex16
-           MOV.B   R4L,#':'
-           CALL    cout
-           CALL    space
-           MOV.B   R4L,#'('
-           CALL    cout
-           MOV.B   R3L,dpl
-           MOV.B   R3H,dph
-           MOVS    R4L,#0
-           MOVC.B  A,[A+dptr]
-           CALL    phex
-           MOV.W   R6,#prompt10
-           CALL    pcstr
-           CALL    ghex
-           JB      flag0,edit2
-           BCS     edit2
-           MOV.B   dpl,R3L
-           MOV.B   dph,R3H
-           MOVX.B  [R6],R4L
-           CALL    newline
-           ADDS.W  R6,#1
-           MOV.B   R3L,dpl
-           MOV.B   R3H,dph
-           JMP     edit1
-edit2:     MOV.W   R6,#edits2
-           CALL    pcstr
-           RET
-
-;---------------------------------------------------------;
-
-dir:
-           MOV.W   R6,#prompt9
-           CALL    pcstr
-           MOV.B   R0L,#21
-dir0a:     CALL    space
-           DJNZ.B  R0L,dir0a
-           MOV.W   R6,#prompt9b
-           CALL    pcstr
-
-           MOV.B   dph,#high bmem
-dir1:      CALL    find             ;find the next program in memory
-           BCS     dir2
-dir_end:   CALL    newline          ;we're done if no more found
-           RET
-dir2:
-           CALL    space
-           CALL    space
-           MOV.B   dpl,#32          ;print its name
-           CALL    pstr
-           MOV.B   dpl,#32          ;how long is the name
-           CALL    lenstr
-           MOV.B   R4L,#33
-           CLR     carry
-           SUBB.B  R4L,R0L
-           MOV.B   R0L,R4L
-           MOV.B   R4L,#' '         ;print the right # of spaces
-dir3:      CALL    cout
-           DJNZ.B  R0L,dir3
-           MOV.B   dpl,#0
-           CALL    phex16           ;print the memory location
-           MOV.B   R0L,#6
-           MOV.B   R4L,#' '
-dir4:      CALL    cout
-           DJNZ.B  R0L,dir4
-           MOV.B   dpl,#4           ;now figure out what type it is
-           MOVS    R4L,#0
-           MOVC.B  A,[A+dptr]
-           MOV.B   R1L,dph          ;save this, we're inside a search
-
-dir5:      CJNE.B  R4L,#254,dir5b
-           MOV.W   R6,#type1        ;it's an external command
-           BR      dir7
-dir5b:     CJNE.B  R4L,#255,dir5c
-           MOV.W   R6,#type1a       ;it's some system thing
-           BR      dir7
-dir5c:     CJNE.B  R4L,#253,dir5d
-           MOV.W   R6,#type1b       ;it's a startup routine
-           BR      dir7
-dir5d:     CJNE.B  R4L,#35,dir5e
-           MOV.W   R6,#type2        ;it's an ordinary program
-           BR      dir7
-dir5e:     CJNE.B  R4L,#143,dir5f
-           MOV.W   R6,#type3        ;it's a background task
-           BR      dir7
-dir5f:     CJNE.B  R4L,#69,dir5g
-           MOV.W   R6,#type4        ;it's a data file
-           BR      dir7
-dir5g:
-dir6:      MOV.W   R6,#type5        ;who knows what the hell it is
-
-dir7:      CALL    pcstr          ;print out the type
-           MOV.B   dph,R1L          ;go back and find the next one
-           CALL    newline
-           CJNE.B  dph,#high emem, dir8     ;did we just print the last one?
-           JMP     dir_end
-dir8:      ADDS.B  dph,#1
-           JMP     dir1
-
-
-;   type1=Ext Command
-;  type1a=Misc System Thing
-;  type1b=Power-Up Code
-;   type2=Program
-;   type3=Background Task
-;   type4=Data File
-;   type5=???????
-
-;---------------------------------------------------------;
-
-
-run:
-           CALL    newline
-           CALL    newline
-       jmp     0xF000
-
-
-;---------------------------------------------------------;
-
-help:
-           MOV.W   R6,#help1txt
-           CALL    pcstr
-           MOV.B   R2L,#help_key
-           MOV.W   R6,#help_cmd
-           CALL    help2
-           MOV.B   R2L,#dir_key
-           MOV.W   R6,#dir_cmd
-           CALL    help2
-           MOV.B   R2L,#run_key
-           MOV.W   R6,#run_cmd
-           CALL    help2
-           MOV.B   R2L,#dnld_key
-           MOV.W   R6,#dnld_cmd
-           CALL    help2
-           MOV.B   R2L,#upld_key
-           MOV.W   R6,#upld_cmd
-           CALL    help2
-           MOV.B   R2L,#nloc_key
-           MOV.W   R6,#nloc_cmd
-           CALL    help2
-           MOV.B   R2L,#jump_key
-           MOV.W   R6,#jump_cmd
-           CALL    help2
-           MOV.B   R2L,#dump_key
-           MOV.W   R6,#dump_cmd
-           CALL    help2
-           MOV.B   R2L,#xdump_key
-           MOV.W   R6,#xdump_cmd
-           CALL    help2
-           MOV.B   R2L,#intm_key
-           MOV.W   R6,#intm_cmd
-           CALL    help2
-           MOV.B   R2L,#edit_key
-           MOV.W   R6,#edit_cmd
-           CALL    help2
-           MOV.B   R2L,#clrm_key
-           MOV.W   R6,#clrm_cmd
-           CALL    help2
-           MOV.W   R6,#help2txt
-           CALL    pcstr
-           MOV.W   R6,#bmem
-help3:     CALL    find
-           BCC     help4
-           MOV.B   dpl,#4
-           MOVS    R4L,#0
-           MOVC.B  A,[A+dptr]
-           CJNE.B  R4L,#254,help3a  ;only FE is an ext command
-           CALL    space
-           CALL    space
-           ADDS.B  dpl,#1
-           MOVS    R4L,#0
-           MOVC.B  A,[A+dptr]
-           CALL    cout
-           CALL    dash
-           CALL    space
-           MOV.B   dpl,#32
-           CALL    pstr
-           CALL    newline
-help3a:    ADDS.B  dph,#1
-           BR      help3
-help4:
-           CALL    newline
-           RET
-
-help2:                          ;print 11 standard lines
-           CALL    space            ;given key in R4 and name in dptr
-           CALL    space
-           MOV.B   R4L,R2L
-           CALL    cout
-           CALL    dash
-           CALL    space
-           CALL    pcstr
-           CALL    newline
-           RET
-
-;---------------------------------------------------------;
-
-upld:
-
-           CALL    get_mem
-       ;assume we've got the beginning address in r3/r2
-       ;and the final address in r5/r4 (r4=lsb)...
-
-       ;print out what we'll be doing
-           MOV.W   R6,#uplds3
-           CALL    pcstr
-           MOV.B   R4L,R1H
-           CALL    phex
-           MOV.B   R4L,R1L
-           CALL    phex
-           MOV.W   R6,#uplds4
-           CALL    pcstr
-           MOV.B   R4L,R2H
-           CALL    phex
-           MOV.B   R4L,R2L
-           CALL    phex
-           CALL    newline
-
-       ;need to adjust end location by 1...
-           MOV.B   dph,R2H
-           MOV.B   dpl,R2L
-           ADDS.W  R6,#1
-           MOV.B   R2L,dpl
-           MOV.B   R2H,dph
-
-           MOV.W   R6,#prompt7
-           CALL    pcstr
-           CALL    cin
-           CJNE.B  R4L,#27,upld2e
-           JMP     abort_it
-upld2e:    CALL    newline
-           MOV.B   dpl,R1L
-           MOV.B   dph,R1H
-
-upld3:     MOV.B   R4L,R2L          ;how many more bytes to output??
-           CLR     carry
-           SUBB.B  R4L,dpl
-           MOV.B   R1L,R4L
-           MOV.B   R4L,R2H
-           SUBB.B  R4L,dph
-           JNZ     upld4            ;if >256 left, then do next 16
-           MOV.B   R4L,R1L
-           JZ      upld7            ;if we're all done
-           AND.B   R4L,#11110000Q
-           JNZ     upld4            ;if >= 16 left, then do next 16
-           BR      upld5            ;otherwise just finish it off
-upld4:     MOV.B   R1L,#16
-upld5:     MOV.B   R4L,#':'         ;begin the line
-           CALL    cout
-           MOV.B   R4L,R1L
-           CALL    phex             ;output # of data bytes
-           CALL    phex16           ;output memory location
-           MOV.B   R4L,dph
-           ADD.B   R4L,dpl
-           ADD.B   R4L,R1L
-           MOV.B   R1H,R4L          ;r3 will become checksum
-           MOVS    R4L,#0
-           CALL    phex             ;output 00 code for data
-upld6:     MOVS    R4L,#0
-           MOVC.B  A,[A+dptr]
-           CALL    phex             ;output each byte
-           ADD.B   R4L,R1H
-           MOV.B   R1H,R4L
-           ADDS.W  R6,#1
-           DJNZ.B  R1L,upld6        ;do however many bytes we need
-           MOV.B   R4L,R1H
-           CPL.B   R4L
-           ADDS.B  R4L,#1
-           CALL    phex             ;and finally the checksum
-           CALL    newline
-           CALL    esc
-           BCC     upld3            ;keep working if no esc pressed
-           BR      abort_it
-upld7:     MOV.B   R4L,#':'
-           CALL    cout
-           MOVS    R4L,#0
-           CALL    phex
-           CALL    phex
-           CALL    phex
-           ADDS.B  R4L,#1
-           CALL    phex
-           MOV.B   R4L,#255
-           CALL    phex
-upld8:     CALL    newline
-           CALL    newline
-           RET
-
-
-;---------------------------------------------------------;
-
-get_mem:     ;this thing gets the begin and end locations for
-            ;a few commands.  If an esc or enter w/ no input,
-            ;it pops it's own return and returns to the menu
-            ;(nasty programming, but we need tight code for 4k rom)
-           CALL    newline
-           CALL    newline
-           MOV.W   R6,#beg_str
-           CALL    pcstr
-           CALL    ghex16
-           BCS     pop_it
-           JB      flag0,pop_it
-           PUSH.B  dph
-           PUSH.B  dpl
-           CALL    newline
-           MOV.W   R6,#end_str
-           CALL    pcstr
-           CALL    ghex16
-           MOV.B   R2H,dph
-           MOV.B   R2L,dpl
-           POP.B   acc
-           MOV.B   R1L,R4L
-           POP.B   acc
-           MOV.B   R1H,R4L
-           BCS     pop_it
-           JB      flag0,pop_it
-           CALL    newline
-           RET
-
-pop_it:    POP.B   acc
-           POP.B   acc
-abort_it:
-           CALL    newline
-           MOV.W   R6,#abort
-           CALL    pcstr
-           CALL    newline
-           RET
-
-clrm:
-           CALL    get_mem
-           MOV.W   R6,#sure
-           CALL    pcstr
-           CALL    cin
-           CALL    upper
-           CJNE.B  R4L,#'Y',abort_it
-           CALL    newline
-           CALL    newline
-     ;now we actually do it
-
-clrm2:     MOV.B   dph,R1H
-           MOV.B   dpl,R1L
-clrm3:     MOVS    R4L,#0
-           CALL    smart_wr
-               cmp.w   r6, r2
-               bne             clrm4
-           RET
-clrm4:     ADDS.W  R6,#1
-           BR      clrm3
-
-
-
-;---------------------------------------------------------;
-
-intm:      CALL    newline
-           MOVs.w   r5,#0
-intm2:     CALL    newline
-           CJNE.w  r5, #512, intm3
-           CALL    newline
-           RET
-intm3:  mov.b  r4l,r5h
-       call    phex   
-       MOV.B   R4L,R5L
-           CALL    phex
-           MOV.B   R4L,#':'
-           CALL    cout
-intm4:     CALL    space
-           MOV.B   R4L,[r5+]
-           CALL    phex
-           MOV.B   R4L,R5L
-           AND.B   R4L,#00001111Q
-           JNZ     intm4
-           BR      intm2
-
-
-
-;---------------------------------------------------------;
-;                                                         ;
-;   Subroutines for memory managment and non-serial I/O   ;
-;                                                         ;
-;---------------------------------------------------------;
-
-
-;finds the next header in the external memory.
-;  Input DPTR=point to start search (only MSB used)
-;  Output DPTR=location of next module
-;    C=set if a header found, C=clear if no more headers
-find:      MOV.B   dpl,#0
-           MOVS    R4L,#0
-           MOVC.B  A,[A+dptr]
-           CJNE.B  R4L,#0xA5,find3
-           ADDS.W  R6,#1
-           MOVS    R4L,#0
-           MOVC.B  A,[A+dptr]
-           CJNE.B  R4L,#0xE5,find3
-           ADDS.W  R6,#1
-           MOVS    R4L,#0
-           MOVC.B  A,[A+dptr]
-           CJNE.B  R4L,#0xE0,find3
-           ADDS.W  R6,#1
-           MOVS    R4L,#0
-           MOVC.B  A,[A+dptr]
-           CJNE.B  R4L,#0xA5,find3
-           MOV.B   dpl,#0           ;found one here!
-           SETB    carry
-           RET
-find3:
-           CJNE.B  dph, #high emem, find4    ;did we just check the end
-           CLR     carry
-           RET
-find4:     ADDS.B  dph,#1           ;keep on searching
-           BR      find
-
-
-
-
-;Write to ordinary RAM.  Carry bit will indicate
-;if the value was successfully written, C=1 if not written.
-
-
-smart_wr:
-           PUSH.B  acc
-           PUSH.B  R4H
-           MOV.B   R4H,R4L
-wr_ram:    MOV.B   R4L,R4H
-           MOVX.B  [R6],R4L         ;write the value to memory
-           MOVS    R4L,#0
-           MOVC.B  A,[A+dptr]       ;read it back from code memory
-           CLR     carry
-           SUBB.B  R4L,R4H
-           JZ      smwrok
-           MOVX.B  R4L,[R6]         ;read it back from data memory
-           CLR     carry
-           SUBB.B  R4L,R4H
-           JZ      smwrok
-smwrbad:   SETB    carry
-           BR      smwrxit
-smwrok:    CLR     carry
-smwrxit:   POP.B   R4H
-           POP.B   acc
-           RET
-
-
-
-;---------------------------------------------------------;
-;                                                         ;
-;       Power-On initialization code and such...          ;
-;                                                         ;
-;---------------------------------------------------------;
-
-;first the hardware has to get initialized.
-
-poweron:
-       mov.w   r7, #stack
-       mov.b   wdcon, #0       ;shut off watchdog
-       mov.b   wfeed1, #$a5
-       mov.b   wfeed2, #$5a
-
-       ;or.b   p1cfga, #$C0            ;for testing
-       ;or.b   p1cfgb, #$C0            ;for testing
-
-       ;clr            p1.7            ;for testing
-
-       ;no automatic baud rate detection anymore
-autobaud:
-           MOV.B   tcon,#0
-           MOV.B   R4L,#baud_const
-           MOV.B   tl1,R4L
-           MOV.B   rtl1,R4L
-           MOV.B   tmod,#$22       ;set timer #1 for 8 bit auto-reload
-           MOV.B   s0con,#$52
-           SETB    tr1              ;start the baud rate timer
-           MOV.w   r5, #2000
-ab_loop1:  DJNZ.w  r5, ab_loop1
-
-       ;clr            p1.6            ;for testing
-
-
-welcome:
-           MOV.B   R0L,#24
-welcm2:    CALL    newline
-           DJNZ.B  R0L,welcm2
-
-       ;setb   p1.7            ;for testing
-
-           MOV.B   R0L,#15
-           MOV.B   R4L,#' '
-welcm4:    CALL    cout
-           DJNZ.B  R0L,welcm4
-           MOV.W   R6,#logon1
-           CALL    pcstr
-           MOV.W   R6,#logon2
-           CALL    pcstr
-           ;CALL    dir              ;skip dir for now
-               mov.w   r3, #pgm
-           JMP     menu
-
-
-
-
-
-
-;---------------------------------------------------------;
-;                                                         ;
-;     More subroutines, but less frequent used            ;
-;                                                         ;
-;---------------------------------------------------------;
-
-
-
-
-
-pint8u: ;prints the unsigned 8 bit value in Acc in base 10
-           PUSH.B  R4H
-           PUSH.B  acc
-           BR      pint8b
-
-pint8:  ;prints the signed 8 bit value in Acc in base 10
-           PUSH.B  R4H
-           PUSH.B  acc
-           JNB     R4L.7,pint8b
-           MOV.B   R4L,#'-'
-           CALL    cout
-           POP.B   acc
-           PUSH.B  acc
-           CPL.B   R4L
-           ADD.B   R4L,#1
-pint8b:    MOV.B   R4H,#100
-           DIVU.B R4L,R4H
-           SETB    flag0
-           JZ      pint8c
-           CLR     flag0
-           ADD.B   R4L,#'0'
-           CALL    cout
-pint8c:    MOV.B   R4L,R4H
-           MOV.B   R4H,#10
-           DIVU.B R4L,R4H
-           JNB     flag0,pint8d
-           JZ      pint8e
-pint8d:    ADD.B   R4L,#'0'
-           CALL    cout
-pint8e:    MOV.B   R4L,R4H
-           ADD.B   R4L,#'0'
-           CALL    cout
-           POP.B   acc
-           POP.B   R4H
-           RET
-
-
-
-       ;print 16 bit unsigned integer in DPTR (r6), using base 10.
-pint16u:  
-                       push.w  r2, r3, r4
-           CLR     flag0
-pint16a:   ;ten-thousands digit
-                       mov.w   r2, r6
-                       movs.w  r3, #0
-                       div.d   r2, #10000
-                       xch             r2, r3
-                       mov.b   r4l, r3l
-            JZ      pint16b
-           ADD.B   R4L,#'0'
-           CALL    cout
-           SETB    flag0
-pint16b:   ;thousands digit
-                       movs.w  r3, #0
-                       div.d   r2, #1000
-                       xch             r2, r3
-                       mov.b   r4l, r3l
-           JNZ     pint16c
-           JNB     flag0,pint16d
-pint16c:   ADD.B   R4L,#'0'
-           CALL    cout
-           SETB    flag0
-pint16d:   ;hundreds digit
-                       div.w   r2, #100
-                       xch             r2h, r2l
-                       mov.b   r4l, r2h
-           JNZ     pint16e
-           JNB     flag0,pint16f
-pint16e:   ADD.B   R4L,#'0'
-           CALL    cout
-           SETB    flag0
-pint16f:    ;tens digit
-           DIVU.B R2L, #10
-                       mov.b   r4l, r2l
-           JNZ     pint16g
-           JNB     flag0,pint16h
-pint16g:   ADD.B   R4L,#'0'
-           CALL    cout
-pint16h:  ;ones digit
-                  MOV.B   R4L,R2h          ;and finally the ones digit
-           ADD.B   R4L,#'0'
-           CALL    cout
-           pop.w       r2, r3, r4
-           RET
-
-
-
-upper:  ;converts the ascii code in Acc to uppercase, if it is lowercase
-           PUSH.B  acc
-           CLR     carry
-           SUBB.B  R4L,#97
-           BCS     upper2           ;is it a lowercase character
-           SUBB.B  R4L,#26
-           BCC     upper2
-           POP.B   acc
-           ADD.B   R4L,#224         ;convert to uppercase
-           RET
-upper2:    POP.B   acc              ;don't change anything
-           RET
-
-
-lenstr:    MOV.B   R0L,#0           ;returns length of a string in r0
-           PUSH.B  acc
-lenstr1:   MOVS    R4L,#0
-           MOVC.B  A,[A+dptr]
-           JZ      lenstr2
-           MOV     C,R4L.7
-           ADDS.B  R0L,#1
-           BCS     lenstr2
-           ADDS.W  R6,#1
-           BR      lenstr1
-lenstr2:   POP.B   acc
-           RET
-
-
-;pcstr prints the compressed strings.  A dictionary of 128 words is
-;stored in 4 bit packed binary format.  When pcstr finds a byte in
-;a string with the high bit set, it prints the word from the dictionary.
-;A few bytes have special functions and everything else prints as if
-;it were an ordinary string.
-
-; special codes for pcstr:
-;    0 = end of string
-;   13 = CR/LF
-;   14 = CR/LF and end of string
-;   31 = next word code should be capitalized
-
-pcstr:         push    r0, r2, r4
-           SETB    flag1
-           SETB    flag0
-pcstr1:    MOVS    R4L,#0
-           MOVC.B  A,[A+dptr]
-           ADDS.W  R6,#1
-           JZ      pcstr2
-           JB      R4L.7,decomp
-           AND.B   R4L,#0x7F
-pcstrs1:   CJNE.B  R4L,#13,pcstrs2
-           CALL    newline
-           SETB    flag1
-           BR      pcstr1
-pcstrs2:   CJNE.B  R4L,#31,pcstrs3
-           CLR     flag0
-           BR      pcstr1
-pcstrs3:   CJNE.B  R4L,#14,pcstrs4
-           CALL    newline
-           BR      pcstr2
-pcstrs4:
-           CLR     flag1
-           CALL    cout
-           BR      pcstr1
-pcstr2:    pop         r0, r2, r4
-           RET
-
-;dcomp actually takes care of printing a word from the dictionary
-
-; dptr = position in packed words table
-; r4=0 if next nibble is low, r4=255 if next nibble is high
-
-decomp:    AND.B   R4L,#0x7F
-           MOV.B   R0L,R4L          ;r0 counts which word
-           JB      flag1,decomp1    ;avoid leading space if first word
-           CALL    space
-decomp1:   CLR     flag1
-                       push    r6
-           MOV.W   R6,#words
-           MOV.B   R2L,#0
-           MOV.B   R4L,R0L
-           JZ      dcomp3
-       ;here we must seek past all the words in the table
-       ;that come before the one we're supposed to print
-           MOV.B   R0H,R4L
-dcomp2:    CALL    get_next_nibble
-           JNZ     dcomp2
-       ;when we get here, a word has been skipped... keep doing
-       ;this until we're pointing to the correct one
-           DJNZ.B  R0H,dcomp2
-dcomp3:        ;now we're pointing to the correct word, so all we have
-       ;to do is print it out
-           CALL    get_next_nibble
-           JZ      dcomp_end
-           CJNE.B  R4L,#15,dcomp4
-       ;the character is one of the 12 least commonly used
-           CALL    get_next_nibble
-           ADDS.B  R4L,#1
-           MOVC.B  A,[A+pc]
-           BR      dcomp5
-           DB      "hfwgybxvkqjz"
-dcomp4:        ;the character is one of the 14 most commonly used
-           ADDS.B  R4L,#1
-           MOVC.B  A,[A+pc]
-           BR      dcomp5
-           DB      "etarnisolumpdc"
-dcomp5:        ;decide if it should be uppercase or lowercase
-           MOV     C,flag0
-           MOV     R4L.5,C
-           SETB    flag0
-           CJNE.B  R0L,#20,dcomp6
-           CLR     R4L.5
-dcomp6:    CJNE.B  R0L,#12,dcomp7
-           CLR     R4L.5
-dcomp7:    CALL    cout
-           BR      dcomp3
-dcomp_end:
-                       pop             r6
-           JMP     pcstr1
-
-get_next_nibble:       ;...and update dptr and r4, of course
-           MOVS    R4L,#0
-           MOVC.B  A,[A+dptr]
-           CJNE.B  R2L,#0,gnn2
-           MOV.B   R2L,#255
-           AND.B   R4L,#00001111Q
-           RET
-gnn2:      MOV.B   R2L,#0
-           ADDS.W  R6,#1
-           RL.B R4L,#4
-           AND.B   R4L,#00001111Q
-           RET
-
-
-;---------------------------------------------------------;
-;                                                         ;
-;        Here begins the data tables and strings          ;
-;                                                         ;
-;---------------------------------------------------------;
-
-;this is the dictionary of 128 words used by pcstr.
-
-words:
-           DB      0x82,0x90,0xE8,0x23,0x86,0x05,0x4C,0xF8
-           DB      0x44,0xB3,0xB0,0xB1,0x48,0x5F,0xF0,0x11
-           DB      0x7F,0xA0,0x15,0x7F,0x1C,0x2E,0xD1,0x40
-           DB      0x5A,0x50,0xF1,0x03,0xBF,0xBA,0x0C,0x2F
-           DB      0x96,0x01,0x8D,0x3F,0x95,0x38,0x0D,0x6F
-           DB      0x5F,0x12,0x07,0x71,0x0E,0x56,0x2F,0x48
-           DB      0x3B,0x62,0x58,0x20,0x1F,0x76,0x70,0x32
-           DB      0x24,0x40,0xB8,0x40,0xE1,0x61,0x8F,0x01
-           DB      0x34,0x0B,0xCA,0x89,0xD3,0xC0,0xA3,0xB9
-           DB      0x58,0x80,0x04,0xF8,0x02,0x85,0x60,0x25
-           DB      0x91,0xF0,0x92,0x73,0x1F,0x10,0x7F,0x12
-           DB      0x54,0x93,0x10,0x44,0x48,0x07,0xD1,0x26
-           DB      0x56,0x4F,0xD0,0xF6,0x64,0x72,0xE0,0xB8
-           DB      0x3B,0xD5,0xF0,0x16,0x4F,0x56,0x30,0x6F
-           DB      0x48,0x02,0x5F,0xA8,0x20,0x1F,0x01,0x76
-           DB      0x30,0xD5,0x60,0x25,0x41,0xA4,0x2C,0x60
-           DB      0x05,0x6F,0x01,0x3F,0x26,0x1F,0x30,0x07
-           DB      0x8E,0x1D,0xF0,0x63,0x99,0xF0,0x42,0xB8
-           DB      0x20,0x1F,0x23,0x30,0x02,0x7A,0xD1,0x60
-           DB      0x2F,0xF0,0xF6,0x05,0x8F,0x93,0x1A,0x50
-           DB      0x28,0xF0,0x82,0x04,0x6F,0xA3,0x0D,0x3F
-           DB      0x1F,0x51,0x40,0x23,0x01,0x3E,0x05,0x43
-           DB      0x01,0x7A,0x01,0x17,0x64,0x93,0x30,0x2A
-           DB      0x08,0x8C,0x24,0x30,0x99,0xB0,0xF3,0x19
-           DB      0x60,0x25,0x41,0x35,0x09,0x8E,0xCB,0x19
-           DB      0x12,0x30,0x05,0x1F,0x31,0x1D,0x04,0x14
-           DB      0x4F,0x76,0x12,0x04,0xAB,0x27,0x90,0x56
-           DB      0x01,0x2F,0xA8,0xD5,0xF0,0xAA,0x26,0x20
-           DB      0x5F,0x1C,0xF0,0xF3,0x61,0xFE,0x01,0x41
-           DB      0x73,0x01,0x27,0xC1,0xC0,0x84,0x8F,0xD6
-           DB      0x01,0x87,0x70,0x56,0x4F,0x19,0x70,0x1F
-           DB      0xA8,0xD9,0x90,0x76,0x02,0x17,0x43,0xFE
-           DB      0x01,0xC1,0x84,0x0B,0x15,0x7F,0x02,0x8B
-           DB      0x14,0x30,0x8F,0x63,0x39,0x6F,0x19,0xF0
-           DB      0x11,0xC9,0x10,0x6D,0x02,0x3F,0x91,0x09
-           DB      0x7A,0x41,0xD0,0xBA,0x0C,0x1D,0x39,0x5F
-           DB      0x07,0xF2,0x11,0x17,0x20,0x41,0x6B,0x35
-           DB      0x09,0xF7,0x75,0x12,0x0B,0xA7,0xCC,0x48
-           DB      0x02,0x3F,0x64,0x12,0xA0,0x0C,0x27,0xE3
-           DB      0x9F,0xC0,0x14,0x77,0x70,0x11,0x40,0x71
-           DB      0x21,0xC0,0x68,0x25,0x41,0xF0,0x62,0x7F
-           DB      0xD1,0xD0,0x21,0xE1,0x62,0x58,0xB0,0xF3
-           DB      0x05,0x1F,0x73,0x30,0x77,0xB1,0x6F,0x19
-           DB      0xE0,0x19,0x43,0xE0,0x58,0x2F,0xF6,0xA4
-           DB      0x14,0xD0,0x23,0x03,0xFE,0x31,0xF5,0x14
-           DB      0x30,0x99,0xF8,0x03,0x3F,0x64,0x22,0x51
-           DB      0x60,0x25,0x41,0x2F,0xE3,0x01,0x56,0x27
-           DB      0x93,0x09,0xFE,0x11,0xFE,0x79,0xBA,0x60
-           DB      0x75,0x42,0xEA,0x62,0x58,0xA0,0xE5,0x1F
-           DB      0x53,0x4F,0xD1,0xC0,0xA3,0x09,0x42,0x53
-           DB      0xF7,0x12,0x04,0x62,0x1B,0x30,0xF5,0x05
-           DB      0xF7,0x69,0x0C,0x35,0x1B,0x70,0x82,0x2F
-           DB      0x2F,0x14,0x4F,0x51,0xC0,0x64,0x25,0x00
-
-;STR
-
-logon1:    DB      "Welcome",128,148,"2 (beta7,XA) by",31,248,31,254,13,14
-logon2:    DB      32,32,"See",148,"2.DOC,",148,"2.EQU",164
-           DB      148,"2.HDR",180,213,141,".",14
-abort:     DB      " ",31,158,31,160,"!",14
-prompt1:   DB      148,"2 (beta7,XA) Loc:",0
-prompt2:   DB      ">",160
-prompt3:   DB      134,202,130,'(',0
-prompt4:   DB      "),",149,140,128,200,": ",0
-prompt5:   DB      31,151,130,195,"s",199,166,131,","
-           DB      186," JUMP",128,134,161,"r",130,13,14
-prompt6:   DB      13,13,31,135,131,129,": ",0
-prompt7:   DB      31,228,251," key: ",0
-prompt8:   DB      13,13,31,136,128,131,129," (",0
-prompt9:   DB      13,13,31,130,31,253,0
-prompt9b:  DB      31,129,32,32,32,32,32,31,201,14
-prompt10:  DB      ") ",31,135,31,178,": ",0
-beg_str:   DB      "First",31,129,": ",0
-end_str:   DB      "Last",31,129,":",32,32,0
-sure:      DB      31,185,161," sure?",0
-edits1:    DB      13,13,31,156,154,146,",",140,128,200,14
-edits2:    DB      "  ",31,156,193,",",142,129,247,13,14
-dnlds1:    DB      13,13,31,159," ascii",249,150,31,152,132,137
-           DB      ",",149,140,128,160,13,14
-dnlds2:    DB      13,31,138,160,"ed",13,14
-dnlds3:    DB      13,31,138,193,"d",13,14
-dnlds4:    DB      "Summary:",14
-dnlds5:    DB      " ",198,"s",145,"d",14
-dnlds6a:   DB      " ",139,145,"d",14
-dnlds6b:   DB      " ",139," written",14
-dnlds7:    DB      31,155,":",14
-dnlds8:    DB      " ",139," unable",128," write",14
-dnlds9:    DB      32,32,"bad",245,"s",14
-dnlds10:   DB      " ",133,159,150,198,14
-dnlds11:   DB      " ",133,132,157,14
-dnlds12:   DB      " ",133," non",132,157,14
-dnlds13:   DB      31,151,155," detected",13,14
-runs1:     DB      13,134,"ning",130,":",13,14
-uplds3:    DB      13,13,"Sending",31,152,132,137,172,32,32,0
-uplds4:    DB      " ",128,32,32,0
-help1txt:  DB      13,13,"Standard",31,158,"s",14
-help2txt:  DB      31,218,31,244,"ed",31,158,"s",14
-type1:     DB      31,154,158,0
-type1a:    DB      31,223,0
-type1b:    DB      31,143,31,226,31,170,0
-type2:     DB      31,130,0
-type3:     DB      "Reserved",0
-type4:     DB      31,239,137,0
-type5:     DB      "???",0
-help_cmd:  DB      31,142,215,209,0
-help_cmd2: DB      31,215,0
-dir_cmd:   DB      31,209,130,"s",0
-run_cmd:   DB      31,134,130,0
-dnld_cmd:  DB      31,138,0
-upld_cmd:  DB      31,147,0
-nloc_cmd:  DB      31,135,129,0
-jump_cmd:  DB      31,136,128,131,129,0
-dump_cmd:  DB  31,132,219,154," code",131,0
-xdump_cmd: db  31,132,219,154," data",131,0
-intm_cmd:  DB      31,132,219,192,131,0
-edit_cmd:  DB      31,156,154,146,0
-clrm_cmd:  DB      31,237,131,0
-erfr_cmd:  DB      31,203,153,144,0
-
-
-
-
-;this code attempts to switch from development mode to run mode
-;on the xa_tiny (8-bit data bus) development board.
-
-       org     0x7000
-
-es      sfr     442h
-pswh    sfr     401h
-
-       ; a bunch of nops, to hopefully flush the xa prefetch buffer
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-
-       ;make a read from location 0x0EF000 to switch modes
-       mov.b   es, #0x0E
-       mov     r0, #0xF000
-       setb    ssel.0
-       mov.b   r4l, [r0]       ;make the mode switch
-       mov.b   r4l, [r0]       ;make the mode switch
-       mov.b   r4l, [r0]       ;make the mode switch
-       mov.b   r4l, [r0]       ;make the mode switch
-
-       ;now read the start vector from location zero
-       movs.b  es, #0
-       movs    r0, #0
-       movc    r1l, [r0+]      ;read psw value into r1
-       movc    r1h, [r0+]
-       movc    r2l, [r0+]      ;read start address into r2
-       movc    r2h, [r0+]
-
-       movs.b  ssel, #0
-       mov.b   pswl, r1l
-       mov.b   pswh, r1h
-       jmp     [r2]
-
-
-
diff --git a/as/xa51/todo b/as/xa51/todo
deleted file mode 100644 (file)
index 91f3496..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-add flag to all symbol structure to remember if it was a line label...
-if a symbol which was a line label is used in immediate addressing,
-it must be considered a branch target.
--- maybe adding an align directive would be enough...
-
-write error messages into list file
-
diff --git a/as/xa51/xa_asm.l b/as/xa51/xa_asm.l
deleted file mode 100644 (file)
index 5366ec1..0000000
+++ /dev/null
@@ -1,326 +0,0 @@
-%{
-/* This file is part of Paul's XA51 Assembler, Copyright 1997,2002 Paul Stoffregen
- *
- * Paul's XA51 Assembler is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2.
- *
- * Paul's XA51 Assembler is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/* Author contact: paul@pjrc.com */
-
-#include <stdio.h>
-#include <string.h>
-#include "xa_main.h"
-#include "xa_asm.tab.h"
-
-extern int inst_size, yylval;
-char line_text[MAX_LINE]={'\0'}, last_line_text[MAX_LINE];
-char lex_sym_name[MAX_SYMBOL];
-extern char base_symbol_name[];
-#define LIST if (p3) strcat(line_text, yytext)
-%}
-
-%%
-
-add\.w         {LIST; inst_size=SIZE16; return ADD;}
-add\.b         {LIST; inst_size=SIZE8; return ADD;}
-add            {LIST; inst_size=UNKNOWN; return ADD;}
-addc\.w                {LIST; inst_size=SIZE16; return ADDC;}
-addc\.b                {LIST; inst_size=SIZE8; return ADDC;}
-addc           {LIST; inst_size=UNKNOWN; return ADDC;}
-adds\.w                {LIST; inst_size=SIZE16; return ADDS;}
-adds\.b                {LIST; inst_size=SIZE8; return ADDS;}
-adds           {LIST; inst_size=UNKNOWN; return ADDS;}
-and\.w         {LIST; inst_size=SIZE16; return AND;}
-and\.b         {LIST; inst_size=SIZE8; return AND;}
-and            {LIST; inst_size=UNKNOWN; return AND;}
-anl            {LIST; inst_size=UNKNOWN; return ANL;}
-asl\.d         {LIST; inst_size=SIZE32; return ASL;}
-asl\.w         {LIST; inst_size=SIZE16; return ASL;}
-asl\.b         {LIST; inst_size=SIZE8; return ASL;}
-asl            {LIST; inst_size=UNKNOWN; return ASL;}
-asr\.d         {LIST; inst_size=SIZE32; return ASR;}
-asr\.w         {LIST; inst_size=SIZE16; return ASR;}
-asr\.b         {LIST; inst_size=SIZE8; return ASR;}
-asr            {LIST; inst_size=UNKNOWN; return ASR;}
-bcc            {LIST; inst_size=UNKNOWN; return BCC;}
-bcs            {LIST; inst_size=UNKNOWN; return BCS;}
-beq            {LIST; inst_size=UNKNOWN; return BEQ;}
-bg             {LIST; inst_size=UNKNOWN; return BG;}
-bge            {LIST; inst_size=UNKNOWN; return BGE;}
-bgt            {LIST; inst_size=UNKNOWN; return BGT;}
-bkpt           {LIST; inst_size=UNKNOWN; return BKPT;}
-bl             {LIST; inst_size=UNKNOWN; return BL;}
-ble            {LIST; inst_size=UNKNOWN; return BLE;}
-blt            {LIST; inst_size=UNKNOWN; return BLT;}
-bmi            {LIST; inst_size=UNKNOWN; return BMI;}
-bne            {LIST; inst_size=UNKNOWN; return BNE;}
-bnv            {LIST; inst_size=UNKNOWN; return BNV;}
-bov            {LIST; inst_size=UNKNOWN; return BOV;}
-bpl            {LIST; inst_size=UNKNOWN; return BPL;}
-br             {LIST; inst_size=UNKNOWN; return BR;}
-call           {LIST; inst_size=UNKNOWN; return CALL;}
-cjne\.w                {LIST; inst_size=SIZE16; return CJNE;}
-cjne\.b                {LIST; inst_size=SIZE8; return CJNE;}
-cjne           {LIST; inst_size=UNKNOWN; return CJNE;}
-clr            {LIST; inst_size=UNKNOWN; return CLR;}
-cmp\.w         {LIST; inst_size=SIZE16; return CMP;}
-cmp\.b         {LIST; inst_size=SIZE8; return CMP;}
-cmp            {LIST; inst_size=UNKNOWN; return CMP;}
-cpl\.w         {LIST; inst_size=SIZE16; return CPL;}
-cpl\.b         {LIST; inst_size=SIZE8; return CPL;}
-cpl            {LIST; inst_size=UNKNOWN; return CPL;}
-da\.b          {LIST; inst_size=SIZE8; return DA;}
-da             {LIST; inst_size=UNKNOWN; return DA;}
-div\.d         {LIST; inst_size=SIZE32; return DIV;}
-div\.w         {LIST; inst_size=SIZE16; return DIV;}
-div\.b         {LIST; inst_size=SIZE8; return DIV;}
-div            {LIST; inst_size=UNKNOWN; return DIV;}
-divu\.d                {LIST; inst_size=SIZE32; return DIVU;}
-divu\.w                {LIST; inst_size=SIZE16; return DIVU;}
-divu\.b                {LIST; inst_size=SIZE8; return DIVU;}
-divu           {LIST; inst_size=UNKNOWN; return DIVU;}
-djnz\.w                {LIST; inst_size=SIZE16; return DJNZ;}
-djnz\.b                {LIST; inst_size=SIZE8; return DJNZ;}
-djnz           {LIST; inst_size=UNKNOWN; return DJNZ;}
-fcall          {LIST; inst_size=UNKNOWN; return FCALL;}
-fjmp           {LIST; inst_size=UNKNOWN; return FJMP;}
-jb             {LIST; inst_size=UNKNOWN; return JB;}
-jbc            {LIST; inst_size=UNKNOWN; return JBC;}
-jmp            {LIST; inst_size=UNKNOWN; return JMP;}
-jnb            {LIST; inst_size=UNKNOWN; return JNB;}
-jnz            {LIST; inst_size=UNKNOWN; return JNZ;}
-jz             {LIST; inst_size=UNKNOWN; return JZ;}
-lea\.w         {LIST; inst_size=SIZE16; return LEA;}
-lea            {LIST; inst_size=UNKNOWN; return LEA;}
-lsr\.d         {LIST; inst_size=SIZE32; return LSR;}
-lsr\.w         {LIST; inst_size=SIZE16; return LSR;}
-lsr\.b         {LIST; inst_size=SIZE8; return LSR;}
-lsr            {LIST; inst_size=UNKNOWN; return LSR;}
-mov\.w         {LIST; inst_size=SIZE16; return MOV;}
-mov\.b         {LIST; inst_size=SIZE8; return MOV;}
-mov            {LIST; inst_size=UNKNOWN; return MOV;}
-movc\.w                {LIST; inst_size=SIZE16; return MOVC;}
-movc\.b                {LIST; inst_size=SIZE8; return MOVC;}
-movc           {LIST; inst_size=UNKNOWN; return MOVC;}
-movs\.w                {LIST; inst_size=SIZE16; return MOVS;}
-movs\.b                {LIST; inst_size=SIZE8; return MOVS;}
-movs           {LIST; inst_size=UNKNOWN; return MOVS;}
-movx\.w                {LIST; inst_size=SIZE16; return MOVX;}
-movx\.b                {LIST; inst_size=SIZE8; return MOVX;}
-movx           {LIST; inst_size=UNKNOWN; return MOVX;}
-mul\.d         {LIST; inst_size=SIZE32; return MUL;}
-mul\.w         {LIST; inst_size=SIZE16; return MUL;}
-mul\.b         {LIST; inst_size=SIZE8; return MUL;}
-mul            {LIST; inst_size=UNKNOWN; return MUL;}
-mulu\.d                {LIST; inst_size=SIZE32; return MULU;}
-mulu\.w                {LIST; inst_size=SIZE16; return MULU;}
-mulu\.b                {LIST; inst_size=SIZE8; return MULU;}
-mulu           {LIST; inst_size=UNKNOWN; return MULU;}
-neg\.w         {LIST; inst_size=SIZE16; return NEG;}
-neg\.b         {LIST; inst_size=SIZE8; return NEG;}
-neg            {LIST; inst_size=UNKNOWN; return NEG;}
-nop            {LIST; inst_size=UNKNOWN; return NOP;}
-norm\.d                {LIST; inst_size=SIZE32; return NORM;}
-norm\.w                {LIST; inst_size=SIZE16; return NORM;}
-norm\.b                {LIST; inst_size=SIZE8; return NORM;}
-norm           {LIST; inst_size=UNKNOWN; return NORM;}
-or\.w          {LIST; inst_size=SIZE16; return OR;}
-or\.b          {LIST; inst_size=SIZE8; return OR;}
-or             {LIST; inst_size=UNKNOWN; return OR;}
-orl            {LIST; inst_size=UNKNOWN; return ORL;}
-pop\.w         {LIST; inst_size=SIZE16; return POP;}
-pop\.b         {LIST; inst_size=SIZE8; return POP;}
-pop            {LIST; inst_size=UNKNOWN; return POP;}
-popu\.w                {LIST; inst_size=SIZE16; return POPU;}
-popu\.b                {LIST; inst_size=SIZE8; return POPU;}
-popu           {LIST; inst_size=UNKNOWN; return POPU;}
-push\.w                {LIST; inst_size=SIZE16; return PUSH;}
-push\.b                {LIST; inst_size=SIZE8; return PUSH;}
-push           {LIST; inst_size=UNKNOWN; return PUSH;}
-pushu\.w       {LIST; inst_size=SIZE16; return PUSHU;}
-pushu\.b       {LIST; inst_size=SIZE8; return PUSHU;}
-pushu          {LIST; inst_size=UNKNOWN; return PUSHU;}
-reset          {LIST; inst_size=UNKNOWN; return RESET;}
-ret            {LIST; inst_size=UNKNOWN; return RET;}
-reti           {LIST; inst_size=UNKNOWN; return RETI;}
-rl\.w          {LIST; inst_size=SIZE16; return RL;}
-rl\.b          {LIST; inst_size=SIZE8; return RL;}
-rl             {LIST; inst_size=UNKNOWN; return RL;}
-rlc\.w         {LIST; inst_size=SIZE16; return RLC;}
-rlc\.b         {LIST; inst_size=SIZE8; return RLC;}
-rlc            {LIST; inst_size=UNKNOWN; return RLC;}
-rr\.w          {LIST; inst_size=SIZE16; return RR;}
-rr\.b          {LIST; inst_size=SIZE8; return RR;}
-rr             {LIST; inst_size=UNKNOWN; return RR;}
-rrc\.w         {LIST; inst_size=SIZE16; return RRC;}
-rrc\.b         {LIST; inst_size=SIZE8; return RRC;}
-rrc            {LIST; inst_size=UNKNOWN; return RRC;}
-setb           {LIST; inst_size=UNKNOWN; return SETB;}
-sext\.w                {LIST; inst_size=SIZE16; return SEXT;}
-sext\.b                {LIST; inst_size=SIZE8; return SEXT;}
-sext           {LIST; inst_size=UNKNOWN; return SEXT;}
-sub\.w         {LIST; inst_size=SIZE16; return SUB;}
-sub\.b         {LIST; inst_size=SIZE8; return SUB;}
-sub            {LIST; inst_size=UNKNOWN; return SUB;}
-subb\.w                {LIST; inst_size=SIZE16; return SUBB;}
-subb\.b                {LIST; inst_size=SIZE8; return SUBB;}
-subb           {LIST; inst_size=UNKNOWN; return SUBB;}
-trap           {LIST; inst_size=UNKNOWN; return TRAP;}
-xch\.w         {LIST; inst_size=SIZE16; return XCH;}
-xch\.b         {LIST; inst_size=SIZE8; return XCH;}
-xch            {LIST; inst_size=UNKNOWN; return XCH;}
-xor\.w         {LIST; inst_size=SIZE16; return XOR;}
-xor\.b         {LIST; inst_size=SIZE8; return XOR;}
-xor            {LIST; inst_size=UNKNOWN; return XOR;}
-
-
-dptr           {LIST; return DPTR;}
-pc             {LIST; return PC;}
-a              {LIST; return A;}
-c              {LIST; return C;}
-usp            {LIST; return USP;}
-
-org            {LIST; return ORG;}
-equ            {LIST; return EQU;}
-sfr            {LIST; return SFR;}
-db             {LIST; return DB;}
-dw             {LIST; return DW;}
-byte           {LIST; return DB;}
-bit            {LIST; return BITDEF;}
-reg            {LIST; return REGDEF;}
-area           {LIST; return AREA;}
-ds             {LIST; return DS;}
-DSEG           {LIST; yylval = AREA_DSEG; return AREA_NAME;}
-BSEG           {LIST; yylval = AREA_BSEG; return AREA_NAME;}
-XSEG           {LIST; yylval = AREA_XSEG; return AREA_NAME;}
-XISEG          {LIST; yylval = AREA_XISEG; return AREA_NAME;}
-XINIT          {LIST; yylval = AREA_XINIT; return AREA_NAME;}
-GSINIT         {LIST; yylval = AREA_GSINIT; return AREA_NAME;}
-GSFINAL                {LIST; yylval = AREA_GSFINAL; return AREA_NAME;}
-HOME           {LIST; yylval = AREA_HOME; return AREA_NAME;}
-SSEG            {LIST; yylval = AREA_SSEG; return AREA_NAME;}
-CSEG           {LIST; yylval = AREA_CSEG; return AREA_NAME;}
-module         {LIST; return MODULE;}
-globl          {LIST; return GLOBL;}
-\(DATA\)       {LIST; return AREA_DESC;}
-\(OVR,XDATA\)  {LIST; return AREA_DESC;}
-\(BIT\)                {LIST; return AREA_DESC;}
-\(XDATA\)      {LIST; return AREA_DESC;}
-\(CODE\)       {LIST; return AREA_DESC;}
-low            {LIST; return LOW;}
-high           {LIST; return HIGH;}
->>             {LIST; return RSHIFT;}
-\<\<           {LIST; return LSHIFT;}
-
-
-R[0-9]         {LIST; yylval = yytext[1] - '0' + WORD_REG; return REG;}
-R1[0-5]                {LIST; yylval = yytext[2] - '0' + 10 + WORD_REG; return REG;}
-R[0-7]L                {LIST; yylval = (yytext[1] - '0') * 2 + BYTE_REG; return REG;}
-R[0-7]H                {LIST; yylval = (yytext[1] - '0') * 2 + 1 + BYTE_REG; return REG;}
-
-
-[a-z_][a-z0-9_]*       {
-                               LIST;
-                               if (is_def(yytext)) {
-                                       yylval = get_value(yytext);
-                               } else {
-                                       yylval = 0;
-                                       if (p3) error("Symbol undefined");
-                               }
-                               /* keep name in lex_sym_name since yytext */
-                               /* could be overwritten if the parser does */
-                               /* a lookahead operation */
-                               strcpy(lex_sym_name, yytext);
-                               if (is_def(lex_sym_name)) {
-                                       yylval = get_value(lex_sym_name);
-                                       /* return correct type if special */
-                                       if (is_bit(lex_sym_name)) return BIT;
-                                       if (is_reg(lex_sym_name)) return REG;
-                               }
-                               return WORD;
-                       }
-[0-9]+\$               {
-                               LIST;
-                               /* should print error if base_symbol_name */
-                               /* is not defined */
-                               sprintf(lex_sym_name, "%s:%s",
-                                       base_symbol_name, yytext);
-                               if (is_def(lex_sym_name)) {
-                                       yylval = get_value(lex_sym_name);
-                               } else {
-                                       yylval = 0;
-                                       if (p3) error("Symbol undefined");
-                               }
-                               return WORD;
-                       }
-[01]+[bq]              {
-                               LIST;
-                               yylval = binary2int(yytext);
-                               return NUMBER;
-                       }
-0x[0-9a-f]+            {
-                               LIST;
-                               sscanf(yytext, "%*c%*c%x", &yylval);
-                               return NUMBER;
-                       }
-[0-9a-f]+[h]           {
-                               LIST;
-                               sscanf(yytext, "%x%*[hH]", &yylval);
-                               return NUMBER;
-                       }
-\$[0-9a-f]+            {
-                               LIST;
-                               sscanf(yytext, "$%x", &yylval);
-                               return NUMBER;
-                       }
--?[0-9]+               {
-                               LIST;
-                               sscanf(yytext, "%d", &yylval);
-                               return NUMBER;
-                       }
-\'.\'                  {
-                               LIST;
-                               yylval = (int)yytext[1];
-                               return CHAR;
-                       }
-\'\\.\'                        {
-                               LIST;
-                               switch (yytext[1]) {
-                                       case 'n':
-                                       case 'N': yylval = 10; break;
-                                       case 'r':
-                                       case 'R': yylval = 13; break;
-                                       case '0': yylval = 0; break;
-                                       default:  yylval = (int)yytext[1];
-                                       /* print a warning here */
-                               }
-                               return CHAR;
-                       }
-\"[^"\n]*["\n]         {
-                               LIST;
-                               return STRING;
-                       }
-
-;[^\n]*                {LIST; /* comments */}
-[ \t\r]                {LIST; /* whitespace */}
-
-\n             {
-                       strcpy(last_line_text, line_text);
-                       line_text[0] = '\0';
-                       ++lineno;
-                       return EOL;
-               }
-
-.              {LIST; return yytext[0];}
-
-%%
diff --git a/as/xa51/xa_asm.y b/as/xa51/xa_asm.y
deleted file mode 100644 (file)
index 4b87ea3..0000000
+++ /dev/null
@@ -1,1330 +0,0 @@
-%{
-/* This file is part of Paul's XA51 Assembler, Copyright 1997,2002 Paul Stoffregen
- *
- * Paul's XA51 Assembler is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2.
- *
- * Paul's XA51 Assembler is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/* Author contact: paul@pjrc.com */
-
-/* parser for the 51-XA assembler, Paul Stoffregen, July 1997 */
-#include <stdio.h>
-
-#include "xa_main.h"
-
-int op[MAX_DB];
-int size;
-int inst_size;
-int arith_opcode, short_opcode, num_op, opcode0, opcode1;
-int shift_imm_opcode, shift_reg_opcode, rotate_opcode;
-int stack_addr_opcode, stack_reg_opcode, branch_opcode;
-int rlist_reg_bank, rlist_bitmask, rlist_size;
-int db_count, dw_count, i;
-char symbol_name[MAX_SYMBOL], base_symbol_name[MAX_SYMBOL]={'\0'};
-char expr_var[MAX_SYMBOL]={0,0,0,'\0'};
-
-extern char lex_sym_name[];
-extern int yylex();
-
-extern void yyrestart(FILE *new_file);
-extern char * disasm(int byte, int memory_location);
-extern void hexout(int byte, int memory_location, int end);
-void error(char *s);
-
-static int bitmask[]={1, 2, 4, 8, 16, 32, 64, 128};
-
-%}
-
-%token ADD ADDC ADDS AND ANL ASL ASR BCC BCS BEQ BG BGE BGT
-%token BKPT BL BLE BLT BMI BNE BNV BOV BPL BR CALL CJNE CLR
-%token CMP CPL DA DIV DIVU DJNZ FCALL FJMP JB JBC JMP JNB JNZ
-%token JZ LEA LSR MOV MOVC MOVS MOVX MUL MULU NEG NOP NORM
-%token OR ORL POP POPU PUSH PUSHU RESET RET RETI RL RLC RR RRC
-%token SETB SEXT SUB SUBB TRAP XCH XOR
-%token REG DPTR PC A C USP
-%token WORD BIT NUMBER CHAR STRING EOL LOCAL_LABEL
-%token ORG EQU SFR DB DW BITDEF REGDEF LOW HIGH
-%token RSHIFT LSHIFT
-%token AREA AREA_NAME AREA_DESC DS
-%token MODULE GLOBL 
-
-%left '&' '|' '^'
-%left RSHIFT LSHIFT
-%left '+' '-'
-%left '*' '/'
-%nonassoc UNARY
-
-%%
-
-all:           line
-             | line all;
-
-line:          linesymbol ':' linenosym {
-                       if (p1) {
-                               build_sym_list(symbol_name);
-                               if (current_area == AREA_BSEG) {
-                                       mk_bit(symbol_name);
-                               }
-                       }
-                       if (p1 || p2) assign_value(symbol_name, MEM_POS);
-                       MEM_POS += $3;
-               }
-             | linenosym {
-                       MEM_POS += $1;
-               }
-
-linenosym:     directive EOL {
-                       if (p3) out(op, $1);
-                       $$ = $1;
-               }
-             | instruction EOL {
-                       if (p3) out(op, $1);
-                       $$ = $1;
-               }
-            | EOL {
-                       if (p3) out(NULL, 0);
-                       $$ = 0;
-               }
-            | error EOL        /* try to recover from any parse error */
-
-
-directive:     '.' ORG expr {
-                       MEM_POS = $3;
-                       $$ = 0;
-               }
-            | ORG expr {
-                       MEM_POS = $2;
-                       $$ = 0;
-               }
-             | '.' EQU symbol ',' expr { 
-                       if (p1) build_sym_list(symbol_name);
-                       if (p1 || p2) assign_value(symbol_name, $5);
-                       $$ = 0;
-               }
-             | normal_or_bit_symbol '=' expr {
-                       if (p1) build_sym_list(symbol_name);
-                       if (p1 || p2) assign_value(symbol_name, $3);
-               }
-            | symbol SFR expr {
-                       if (p1) build_sym_list(symbol_name);
-                       if (p1 || p2) assign_value(symbol_name, $3);
-                       if (p1 || p2) mk_sfr(symbol_name);
-                       $$ = 0;
-               }
-            | '.' BITDEF bitsymbol ',' bit {
-                       if (p1) {
-                               build_sym_list(symbol_name);
-                               mk_bit(symbol_name);
-                       }
-                       if (p1 || p2) assign_value(symbol_name, $5);
-                       $$ = 0;
-               }
-            | bitsymbol BITDEF bit {
-                       if (p1) {
-                                build_sym_list(symbol_name);
-                                mk_bit(symbol_name);
-                        }
-                        if (p1 || p2) assign_value(symbol_name, $3);
-                        $$ = 0;
-                }
-            | bitsymbol BITDEF expr {
-                       if (p1) {
-                                build_sym_list(symbol_name);
-                                mk_bit(symbol_name);
-                        }
-                        if (p1 || p2) assign_value(symbol_name, $3);
-                        $$ = 0;
-                }
-            | '.' REGDEF regsymbol ',' REG {
-                       if (p1) {
-                               build_sym_list(symbol_name);
-                               mk_reg(symbol_name);
-                       }
-                       if (p1 || p2) assign_value(symbol_name, $5);
-                       $$ = 0;
-               }
-            | regsymbol REGDEF REG {
-                       if (p1) {
-                                build_sym_list(symbol_name);
-                                mk_reg(symbol_name);
-                        }
-                        if (p1 || p2) assign_value(symbol_name, $3);
-                        $$ = 0;
-                }
-
-             | '.' db_directive bytes {
-                       $$ = db_count;
-               }
-            | '.' dw_directive words {
-                       $$ = dw_count;
-               }
-            | '.' AREA AREA_NAME AREA_DESC {
-                       if ($3 < 0 || $3 >= NUM_AREAS) {
-                               error("Illegal Area Directive");
-                       }
-                       symbol_name[0] = '\0';
-                       current_area = $3;
-                       $$ = 0;
-               }
-            | '.' MODULE WORD {
-                       /* ignore module definition */
-                       $$ = 0;
-               }
-            | '.' GLOBL WORD {
-                       /* ignore global symbol declaration */
-                       $$ = 0;
-               }
-            | '.' GLOBL bit {
-                       /* ignore bit symbol declaration */
-                       $$ = 0;
-               }
-            | '.' DS expr {
-                       /* todo: if CSEG, emit some filler bytes */
-                       $$ = $3;
-               }
-
-db_directive:  DB {db_count = 0;}
-
-
-linesymbol:    normal_or_bit_symbol  { 
-                       strcpy(symbol_name, lex_sym_name);
-                       if (!strchr(lex_sym_name, ':')) {
-                               /* non-local label, remember base name */
-                               strcpy(base_symbol_name, lex_sym_name);
-                       }
-                       if (is_target(symbol_name)) pad_with_nop();
-               }
-
-normal_or_bit_symbol: WORD {$$ = $1;}
-               | BIT {$$ = $1;}
-
-bytes:           byte_element
-               | bytes ',' byte_element
-
-byte_element:  expr {
-                       op[db_count] = $1 & 255;
-                       if (++db_count >= MAX_DB) {
-                               error("too many bytes, use two DB");
-                               db_count--;
-                       }
-               }
-               | STRING {
-                       for(i=1; i < strlen(yytext)-1; i++) {
-                               op[db_count++] = yytext[i];
-                               if (db_count >= MAX_DB) {
-                                       error("too many bytes, use two DB");
-                                       db_count--;
-                               }
-                       }
-               }
-
-dw_directive:  DW {dw_count = 0;}
-
-words:           words ',' word_element
-               | word_element
-
-word_element:  expr {
-                       op[dw_count] = $1 & 255;
-                       op[dw_count+1] = ($1 >> 8) & 255;
-                       dw_count += 2;
-                       if (dw_count >= MAX_DB) {
-                               error("too many bytes, use two DW");
-                               db_count -= 2;
-                       }
-               }
-
-
-
-symbol:     WORD  {
-               strcpy(symbol_name, lex_sym_name);
-               }
-
-bitsymbol:    WORD { strcpy(symbol_name, lex_sym_name); }
-           | BIT  { strcpy(symbol_name, lex_sym_name); }
-
-
-regsymbol:    WORD { strcpy(symbol_name, lex_sym_name); }
-           | REG  { strcpy(symbol_name, lex_sym_name); }
-
-bit:   expr '.' expr {
-               if ($3 < 0 || $3 > 7) {
-                       /* only 8 bits in a byte */
-                       error("Only eight bits in a byte");
-               }
-               $$ = 100000;    /* should really check $1 is valid */
-               if ($1 >= 0x20 && $1 <= 0x3F) {
-                       $$ = $1 * 8 + $3;
-               }
-               if ($1 >= 0x400 && $1 <= 0x43F) {
-                       $$ = ($1 - 0x400) * 8 + $3 + 0x200;
-               }
-       }
-       | REG '.' expr {
-               $$ = 100000;
-               if (find_size_reg($1) == SIZE8) {
-                       if ($3 < 0 || $3 > 7)
-                               error("byte reg has only 8 bits");
-                       $$ = reg($1) * 8 + $3;
-               }
-               if (find_size_reg($1) == SIZE16) {
-                       if ($3 < 0 || $3 > 15)
-                               error("word reg has only 16 bits");
-                       $$ = reg($1) * 16 + $3;
-               }
-       }
-       | BIT {$$ = $1;}
-
-jmpaddr:       WORD {
-                       $$ = $1;
-                       if (p1) build_target_list(lex_sym_name);
-               }
-             | NUMBER {
-                       if ($1 & 1) error("Jump target must be aligned");
-                       $$ = $1;
-               }
-
-
-expr:  value   {$$ = $1;}
-       | expr '+' expr {$$ = $1 + $3;}
-       | expr '-' expr {$$ = $1 - $3;}
-       | expr '*' expr {$$ = $1 * $3;}
-       | expr '/' expr {$$ = $1 / $3;}
-       | expr '&' expr {$$ = $1 & $3;}
-       | expr '|' expr {$$ = $1 | $3;}
-       | expr '^' expr {$$ = $1 ^ $3;}
-       | expr RSHIFT expr {$$ = $1 >> $3;}
-       | expr LSHIFT expr {$$ = $1 << $3;}
-       | '-' expr %prec UNARY {$$ = $2 * -1;}
-       | '+' expr %prec UNARY {$$ = $2;}
-       | '(' expr ')' {$$ = $2;}
-       | LOW expr %prec UNARY {$$ = $2 & 255;}
-       | HIGH expr %prec UNARY {$$ = ($2 >> 8) & 255;}
-
-
-value:   NUMBER {$$ = $1;}
-       | CHAR {$$ = $1;}
-       | WORD {$$ = $1; strcpy(expr_var, yytext);}
-
-
-rlist: REG {
-               rlist_bitmask = bitmask[reg($1) % 8];
-               rlist_reg_bank = (reg($1) / 8) ? 1 : 0;
-               rlist_size = find_size_reg($1);
-       }
-       | REG ',' rlist {
-               rlist_bitmask |= bitmask[reg($1) % 8];
-               if (rlist_reg_bank != ((reg($1) / 8) ? 1 : 0))
-                       error("register list may not mix 0-7/8-15 regs");
-               if (rlist_size != find_size_reg($1))
-                       error("register list may not mix 8/16 bit registers");
-       }
-
-
-
-
-
-instruction:
-
-  arith_inst REG ',' REG {
-       $$ = 2;
-       size = find_size2(inst_size, $2, $4);
-       op[0] = arith_opcode * 16 + size * 8 + 1;
-       op[1] = reg($2) * 16 + reg($4);
-  }
-| arith_inst REG ',' '[' REG ']' {
-       $$ = 2;
-       size = find_size1(inst_size, $2);
-       op[0] = arith_opcode * 16 + size * 8 + 2;
-       op[1] = reg($2) * 16 + reg_indirect($5);
-  }
-| arith_inst '[' REG ']' ',' REG {
-       $$ = 2;
-       size = find_size1(inst_size, $6);
-       op[0] = arith_opcode * 16 + size * 8 + 2;
-       op[1] = reg($6) * 16 + 8 + reg_indirect($3);
-  }
-| arith_inst REG ',' '[' REG '+' expr ']' {
-       size = find_size1(inst_size, $2);
-       if ($7 >= -128 && $7 <= 127) {
-               $$ = 3;
-               op[0] = arith_opcode * 16 + size * 8 + 4;
-               op[1] = reg($2) * 16 + reg_indirect($5);
-               op[2] = ($7 >= 0) ? $7 : 256 + $7;
-       } else {
-               $$ = 4;
-               op[0] = arith_opcode * 16 + size * 8 + 5;
-               op[1] = reg($2) * 16 + reg_indirect($5);
-               op[2] = ($7 >= 0) ? msb($7) : msb(65536 + $7);
-               op[3] = ($7 >= 0) ? lsb($7) : lsb(65536 + $7);
-       }
-  }
-| arith_inst '[' REG '+' expr ']' ',' REG {
-       size = find_size1(inst_size, $8);
-       if ($5 >= -128 && $5 <= 127) {
-               $$ = 3;
-               op[0] = arith_opcode * 16 + size * 8 + 4;
-               op[1] = reg($8) * 16 + 8 + reg_indirect($3);
-               op[2] = ($5 >= 0) ? $5 : 256 + $5;
-       } else {
-               $$ = 4;
-               op[0] = arith_opcode * 16 + size * 8 + 5;
-               op[1] = reg($8) * 16 + 8 + reg_indirect($3);
-               op[2] = ($5 >= 0) ? msb($5) : msb(65536 + $5);
-               op[3] = ($5 >= 0) ? lsb($5) : lsb(65536 + $5);
-       }
-  }
-| arith_inst REG ',' '[' REG '+' ']' {
-       $$ = 2;
-       size = find_size1(inst_size, $2);
-       op[0] = arith_opcode * 16 + size * 8 + 3;
-       op[1] = reg($2) * 16 + reg_indirect($5);
-  }
-| arith_inst '[' REG '+' ']' ',' REG {
-       $$ = 2;
-       size = find_size1(inst_size, $7);
-       op[0] = arith_opcode * 16 + size * 8 + 3;
-       op[1] = reg($7) * 16 + 8 + reg_indirect($3);
-  }
-| arith_inst expr ',' REG {
-       $$ = 3;
-       size = find_size1(inst_size, $4);
-       op[0] = arith_opcode * 16 + size * 8 + 6;
-       op[1] = reg($4) * 16 + 8 + msb(direct_addr($2));
-       op[2] = lsb(direct_addr($2));
-  }
-| arith_inst REG ',' expr {
-       $$ = 3;
-       size = find_size1(inst_size, $2);
-       op[0] = arith_opcode * 16 + size * 8 + 6;
-       op[1] = reg($2) * 16 + msb(direct_addr($4));
-       op[2] = lsb(direct_addr($4));
-  }
-| arith_inst REG ',' '#' expr {
-       size = find_size1(inst_size, $2);
-       if (size == SIZE8) {
-               $$ = 3;
-               op[0] = 0x91;
-               op[1] = reg($2) * 16 + arith_opcode;
-               op[2] = imm_data8($5);
-       } else {
-               $$ = 4;
-               op[0] = 0x99;
-               op[1] = reg($2) * 16 + arith_opcode;
-               op[2] = msb(imm_data16($5));
-               op[3] = lsb(imm_data16($5));
-       }
-  }
-| arith_inst '[' REG ']' ',' '#' expr {
-       size = find_size0(inst_size);
-       if (size == SIZE8) {
-               $$ = 3;
-               op[0] = 0x92;
-               op[1] = reg_indirect($3) * 16 + arith_opcode;
-               op[2] = imm_data8($7);
-       } else {
-               $$ = 4;
-               op[0] = 0x9A;
-               op[1] = reg_indirect($3) * 16 + arith_opcode;
-               op[2] = msb(imm_data16($7));
-               op[3] = lsb(imm_data16($7));
-       }
-  }
-| arith_inst '[' REG '+' ']' ',' '#' expr {
-       size = find_size0(inst_size);
-       if (size == SIZE8) {
-               $$ = 3;
-               op[0] = 0x93;
-               op[1] = reg_indirect($3) * 16 + arith_opcode;
-               op[2] = imm_data8($8);
-       } else {
-               $$ = 4;
-               op[0] = 0x9B;
-               op[1] = reg_indirect($3) * 16 + arith_opcode;
-               op[2] = msb(imm_data16($8));
-               op[3] = lsb(imm_data16($8));
-       }
-  }
-| arith_inst '[' REG '+' expr ']' ',' '#' expr {
-       size = find_size0(inst_size);
-       if ($5 >= -128 && $5 <= 127) {
-               if (size == SIZE8) {
-                       $$ = 4;
-                       op[0] = 0x94;
-                       op[1] = reg_indirect($3) * 16 + arith_opcode;
-                       op[2] = ($5 >= 0) ? $5 : 256 + $5;
-                       op[3] = imm_data8($9);
-               } else {
-                       $$ = 5;
-                       op[0] = 0x9C;
-                       op[1] = reg_indirect($3) * 16 + arith_opcode;
-                       op[2] = ($5 >= 0) ? $5 : 256 + $5;
-                       op[3] = msb(imm_data16($9));
-                       op[4] = lsb(imm_data16($9));
-               }
-       } else {
-               if (size == SIZE8) {
-                       $$ = 5;
-                       op[0] = 0x95;
-                       op[1] = reg_indirect($3) * 16 + arith_opcode;
-                       op[2] = ($5 >= 0) ? msb($5) : msb(65536 + $5);
-                       op[3] = ($5 >= 0) ? lsb($5) : lsb(65536 + $5);
-                       op[4] = imm_data8($9);
-               } else {
-                       $$ = 6;
-                       op[0] = 0x9D;
-                       op[1] = reg_indirect($3) * 16 + arith_opcode;
-                       op[2] = ($5 >= 0) ? msb($5) : msb(65536 + $5);
-                       op[3] = ($5 >= 0) ? lsb($5) : lsb(65536 + $5);
-                       op[4] = msb(imm_data16($9));
-                       op[5] = lsb(imm_data16($9));
-               }
-       }
-  }
-| arith_inst expr ',' '#' expr {
-       size = find_size0(inst_size);
-       if (size == SIZE8) {
-               $$ = 4;
-               op[0] = 0x96;
-               op[1] = msb(direct_addr($2)) * 16 + arith_opcode;
-               op[2] = lsb(direct_addr($2));
-               op[3] = imm_data8($5);
-       } else {
-               $$ = 5;
-               op[0] = 0x9E;
-               op[1] = msb(direct_addr($2)) * 16 + arith_opcode;
-               op[2] = lsb(direct_addr($2));
-               op[3] = msb(imm_data16($5));
-               op[4] = lsb(imm_data16($5));
-       }
-  }
-
-/* the next 8 instructions are MOV, but because MOV was used in the */
-/* arith_inst group, it will cause a shift/reduce conflict if used */
-/* directly below... so we're forced to use arith_inst and then */
-/* add a bit of code to make sure it was MOV and not the other ones */
-
-| arith_inst '[' REG '+' ']' ',' '[' REG '+' ']' {
-       /* this addr mode is only valid for MOV */
-       if (arith_opcode != 8) error("Addr mode only valid for MOV (1)");
-       size = find_size0(inst_size);
-       $$ = 2;
-       op[0] = 0x90 + size * 8;
-       op[1] = reg_indirect($3) * 16 + reg_indirect($8);
-  }
-| arith_inst expr ',' '[' REG ']' {
-       /* this addr mode is only valid for MOV */
-       if (arith_opcode != 8) error("Addr mode only valid for MOV (2)");
-       size = find_size0(inst_size);
-       $$ = 3;
-       op[0] = 0xA0 + size * 8;
-       op[1] = 128 + reg_indirect($5) * 16 + msb(direct_addr($2));
-       op[2] = lsb(direct_addr($2));
-  }
-| arith_inst '[' REG ']' ',' expr {
-       /* this addr mode is only valid for MOV */
-       if (arith_opcode != 8) error("Addr mode only valid for MOV (3)");
-       size = find_size0(inst_size);
-       $$ = 3;
-       op[0] = 0xA0 + size * 8;
-       op[1] = reg_indirect($3) * 16 + msb(direct_addr($6));
-       op[2] = lsb(direct_addr($6));
-  }
-| arith_inst expr ',' expr {
-       /* this addr mode is only valid for MOV */
-       if (arith_opcode != 8) error("Addr mode only valid for MOV (4)");
-       size = find_size0(inst_size);
-       $$ = 4;
-       op[0] = 0x97 + size * 8;
-       op[1] = msb(direct_addr($2)) * 16 + msb(direct_addr($4));
-       op[2] = lsb(direct_addr($2));
-       op[3] = lsb(direct_addr($4));
-  }
-| arith_inst REG ',' USP {
-       /* this addr mode is only valid for MOV */
-       if (arith_opcode != 8) error("Addr mode only valid for MOV (5)");
-       $$ = 2;
-       op[0] = 0x90;
-       op[1] = reg($2) * 16 + 15;
-  }
-| arith_inst USP ',' REG {
-       /* this addr mode is only valid for MOV */
-       if (arith_opcode != 8) error("Addr mode only valid for MOV (6)");
-       $$ = 2;
-       op[0] = 0x98;
-       op[1] = reg($4) * 16 + 15;
-  }
-| arith_inst C ',' bit {
-       /* this addr mode is only valid for MOV */
-       if (arith_opcode != 8) error("Addr mode only valid for MOV (7)");
-       $$ = 3;
-       op[0] = 0x08;
-       op[1] = 0x20 + msb(bit_addr($4));
-       op[2] = lsb(bit_addr($4));
-  }
-| arith_inst bit ',' C {
-       /* this addr mode is only valid for MOV */
-       if (arith_opcode != 8) error("Addr mode only valid for MOV (8)");
-       $$ = 3;
-       op[0] = 0x08;
-       op[1] = 0x30 + msb(bit_addr($2));
-       op[2] = lsb(bit_addr($2));
-  }
-
-| MOVC REG ',' '[' REG '+' ']' {
-       size = find_size1(inst_size, $2);
-       $$ = 2;
-       op[0] = 0x80 + size * 8;
-       op[1] = reg($2) * 16 + reg_indirect($5);
-  }
-| MOVC A ',' '[' A '+' DPTR ']' {
-       $$ = 2;
-       op[0] = 0x90;
-       op[1] = 0x4E;
-  }
-| MOVC A ',' '[' A '+' PC ']' {
-       $$ = 2;
-       op[0] = 0x90;
-       op[1] = 0x4C;
-  }
-| MOVX REG ',' '[' REG ']' {
-       $$ = 2;
-       size = find_size1(inst_size, $2);
-       op[0] = 0xA7 + size * 8;
-       op[1] = reg($2) * 16 + reg_indirect($5);
-  }
-| MOVX '[' REG ']' ',' REG {
-       $$ = 2;
-       size = find_size1(inst_size, $6);
-       op[0] = 0xA7 + size * 8;
-       op[1] = reg($6) * 16 + 8 + reg_indirect($3);
-  }
-| XCH REG ',' REG {
-       $$ = 2;
-       size = find_size2(inst_size, $2, $4);
-       op[0] = 0x60 + size * 8;
-       op[1] = reg($2) * 16 + reg($4);
-  }
-| XCH REG ',' '[' REG ']' {
-       $$ = 2;
-       size = find_size1(inst_size, $2);
-       op[0] = 0x50 + size * 8;
-       op[1] = reg($2) * 16 + reg_indirect($5);
-  }
-| XCH REG ',' expr {
-       $$ = 3;
-       size = find_size1(inst_size, $2);
-       op[0] = 0xA0 + size * 8;
-       op[1] = reg($2) * 16 + msb(direct_addr($4));
-        op[2] = lsb(direct_addr($4));
-  }
-| short_data_inst REG ',' '#' expr {
-       $$ = 2;
-       size = find_size1(inst_size, $2);
-       op[0] = short_opcode + size * 8 + 1;
-       op[1] = reg($2) * 16 + imm_data4_signed($5);
-  }
-| short_data_inst '[' REG ']' ',' '#' expr {
-       $$ = 2;
-       size = find_size0(inst_size);
-       op[0] = short_opcode + size * 8 + 2;
-       op[1] = reg_indirect($3) * 16 + imm_data4_signed($7);
-  }
-| short_data_inst '[' REG '+' ']' ',' '#' expr {
-       $$ = 2;
-       size = find_size0(inst_size);
-       op[0] = short_opcode + size * 8 + 3;
-       op[1] = reg_indirect($3) * 16 + imm_data4_signed($8);
-  }
-| short_data_inst '[' REG '+' expr ']' ',' '#' expr {
-       size = find_size0(inst_size);
-       if ($5 >= -128 && $5 <= 127) {
-               $$ = 3;
-               op[0] = short_opcode + size * 8 + 4;
-               op[1] = reg_indirect($3) * 16 + imm_data4_signed($9);
-               op[2] = op[2] = ($5 >= 0) ? $5 : 256 + $5;
-       } else {
-               $$ = 4;
-               op[0] = short_opcode + size * 8 + 5;
-               op[1] = reg_indirect($3) * 16 + imm_data4_signed($9);
-               op[2] = ($5 >= 0) ? msb($5) : msb(65536 + $5);
-               op[3] = ($5 >= 0) ? lsb($5) : lsb(65536 + $5);
-       }
-  }
-| short_data_inst expr ',' '#' expr {
-       $$ = 3;
-       size = find_size0(inst_size);
-       op[0] = short_opcode + size * 8 + 6;
-       op[1] = msb(direct_addr($2)) * 16 + imm_data4_signed($5);
-       op[2] = lsb(direct_addr($2));
-  }
-
-
-
-| ANL C ',' bit {
-       $$ = 3;
-       op[0] = 0x08;
-       op[1] = 0x40 + msb(bit_addr($4));
-       op[2] = lsb(bit_addr($4));
-  }
-| ANL C ',' '/' bit {
-       $$ = 3;
-       op[0] = 0x08;
-       op[1] = 0x50 + msb(bit_addr($5));
-       op[2] = lsb(bit_addr($5));
-  }
-
-| ORL C ',' bit {
-       $$ = 3;
-       op[0] = 0x08;
-       op[1] = 0x60 + msb(bit_addr($4));
-       op[2] = lsb(bit_addr($4));
-  }
-| ORL C ',' '/' bit {
-       $$ = 3;
-       op[0] = 0x08;
-       op[1] = 0x70 + msb(bit_addr($5));
-       op[2] = lsb(bit_addr($5));
-  }
-| CLR bit {
-       $$ = 3;
-       op[0] = 0x08;
-       op[1] = msb(bit_addr($2));
-       op[2] = lsb(bit_addr($2));
-  }
-| SETB bit {
-       $$ = 3;
-       op[0] = 0x08;
-       op[1] = 0x10 + msb(bit_addr($2));
-       op[2] = lsb(bit_addr($2));
-  }
-| logical_shift_inst REG ',' REG {
-       size = find_size1(inst_size, $2);
-       if (find_size_reg($4) != SIZE8)
-               error("Second register in logical shift must be byte size");
-       $$ = 2;
-       op[0] = shift_reg_opcode;
-       switch (size) {
-               case SIZE8:  op[0] += 0; break;
-               case SIZE16: op[0] += 8; break;
-               case SIZE32: op[0] += 12; break;
-       }
-       op[1] = reg($2) * 16 + reg($4);
-  }
-| logical_shift_inst REG ',' '#' expr {
-        size = find_size1(inst_size, $2);
-        $$ = 2;
-       if (shift_imm_opcode == -1)
-               error("NORM may not use a constant");
-        op[0] = shift_imm_opcode;
-        switch (size) {
-                case SIZE8:  op[0] += 0; break;
-                case SIZE16: op[0] += 8; break;
-                case SIZE32: op[0] += 12; break;
-        }
-       switch (size) {
-               case SIZE8:
-               case SIZE16:
-                       op[1] = reg($2) * 16 + imm_data4_unsigned($5);
-                       break;
-               case SIZE32:
-                       op[1] = (reg($2) / 2) * 32 + imm_data5_unsigned($5);
-                       break;
-       }
-  }
-| no_opperand_inst {
-       $$ = num_op;
-       op[0] = opcode0;
-       op[1] = opcode1;
-  }
-
-| TRAP '#' expr {
-       $$ = 2;
-       op[0] = 0xD6;
-       op[1] = 0x30 + imm_data4_unsigned($3);
-  }
-| CPL REG {
-       $$ = 2;
-       size = find_size1(inst_size, $2);
-       op[0] = 0x90 + size * 8;
-       op[1] = reg($2) * 16 + 10;
-  }
-| DA REG {
-       $$ = 2;
-       op[0] = 0x90;
-       op[1] = reg($2) * 16 + 8;
-  }
-| NEG REG {
-       $$ = 2;
-       size = find_size1(inst_size, $2);
-       op[0] = 0x90 + size * 8;
-       op[1] = reg($2) * 16 + 11;
-  }
-| SEXT REG {
-       $$ = 2;
-       size = find_size1(inst_size, $2);
-       op[0] = 0x90 + size * 8;
-       op[1] = reg($2) * 16 + 9;
-  }
-
-| rotate_inst REG ',' '#' expr {
-       $$ = 2;
-       size = find_size1(inst_size, $2);
-       op[0] = rotate_opcode + size * 8;
-       op[1] = reg($2) * 16 + imm_data4_unsigned($5);
-  }
-
-
-| LEA REG ',' REG '+' expr {
-       if ($6 >= -128 && $6 <= 127) {
-               $$ = 3;
-               op[0] = 0x40;
-               op[1] = reg($2) * 16 + reg_indirect($4);
-               op[2] = ($6 >= 0) ? $6 : 256 + $6;
-       } else {
-               op[0] = 0x48;
-               op[1] = reg($2) * 16 + reg_indirect($4);
-               op[2] = ($6 >= 0) ? msb($6) : msb(65536 + $6);
-               op[3] = ($6 >= 0) ? lsb($6) : lsb(65536 + $6);
-       }
-  }
-| stack_inst expr {
-       $$ = 3;
-       size = find_size0(inst_size);
-       op[0] = msb(stack_addr_opcode) + size * 8;
-       op[1] = lsb(stack_addr_opcode) + msb(direct_addr($2));
-       op[2] = lsb(direct_addr($2));
-  }
-| stack_inst rlist {
-       $$ = 2;
-       if (inst_size != UNKNOWN && find_size0(inst_size) != rlist_size)
-               error("inst specifies different size than registers used");
-       op[0] = stack_reg_opcode + rlist_reg_bank * 64 + rlist_size * 8;
-       op[1] = rlist_bitmask;
-  }
-
-
-| MUL REG ',' REG {
-       $$ = 2;
-       size = find_size2(inst_size, $2, $4);
-       op[0] = 0xE6;
-       op[1] = reg($2) * 16 + reg($4);
-  }
-| MULU REG ',' REG {
-       $$ = 2;
-       size = find_size2(inst_size, $2, $4);
-       if (size == SIZE8) {
-               op[0] = 0xE0;
-               op[1] = reg($2) * 16 + reg($4);
-       } else {
-               op[0] = 0xE4;
-               op[1] = reg($2) * 16 + reg($4);
-       }
-  }
-| MUL REG ',' '#' expr {
-       $$ = 2;
-       size = find_size1(inst_size, $2);
-       op[0] = 0xE9;
-       op[1] = reg($2) + 8;
-       op[2] = msb(imm_data16($5));
-       op[3] = lsb(imm_data16($5));
-  }
-| MULU REG ',' '#' expr {
-       size = find_size2(inst_size, $2, $4);
-       if (size == SIZE8) {
-               $$ = 3;
-               op[0] = 0xE8;
-               op[1] = reg($2) * 16;
-               op[2] = imm_data8($5);
-       } else {
-               $$ = 4;
-               op[0] = 0xE9;
-               op[1] = reg($2) * 16;
-               op[2] = msb(imm_data16($5));
-               op[3] = lsb(imm_data16($5));
-       }
-  }
-| DIV REG ',' REG {
-       $$ = 2;
-       size = find_size2(inst_size, $2, $4);
-       switch (size) {
-       case SIZE8:
-               error("Singed DIV can't be 8 bit size"); break;
-       case SIZE16:
-               op[0] = 0xE7;
-               op[1] = reg($2) * 16 + reg($4);
-               break;
-       case SIZE32:
-               op[0] = 0xEF;
-               op[1] = (reg($2) / 2) * 32 + reg($4);
-               break;
-       }
-  }
-| DIVU REG ',' REG {
-       $$ = 2;
-       size = find_size2(inst_size, $2, $4);
-       switch (size) {
-       case SIZE8:
-               op[0] = 0xE1;
-               op[1] = reg($2) * 16 + reg($4);
-               break;
-       case SIZE16:
-               op[0] = 0xE5;
-               op[1] = reg($2) * 16 + reg($4);
-               break;
-       case SIZE32:
-               op[0] = 0xED;
-               op[1] = (reg($2) / 2) * 32 + reg($4);
-               break;
-       }
-  }
-| DIV REG ',' '#' expr { 
-       size = find_size1(inst_size, $2);
-       switch (size) {
-       case SIZE8:
-               error("Singed DIV can't be 8 bit size"); break;
-       case SIZE16:
-               $$ = 3;
-               op[0] = 0xE8;
-               op[1] = reg($2) * 16 + 11;
-               op[2] = imm_data8($5);
-               break;
-       case SIZE32:
-               $$ = 4;
-               op[0] = 0xE9;
-               op[1] = (reg($2) / 2) * 32 + 9;
-               op[2] = msb(imm_data16($5));
-               op[3] = lsb(imm_data16($5));
-               break;
-       }
-  }
-| DIVU REG ',' '#' expr { 
-       size = find_size1(inst_size, $2);
-       switch (size) {
-       case SIZE8:
-               $$ = 3;
-               op[0] = 0xE8;
-               op[1] = reg($2) * 16 + 1;
-               op[2] = imm_data8($5);
-               break;
-       case SIZE16:
-               $$ = 3;
-               op[0] = 0xE8;
-               op[1] = reg($2) * 16 + 3;
-               op[2] = imm_data8($5);
-               break;
-       case SIZE32:
-               $$ = 4;
-               op[0] = 0xE9;
-               op[1] = (reg($2) / 2) * 32 + 1;
-               op[2] = msb(imm_data16($5));
-               op[3] = lsb(imm_data16($5));
-               break;
-       }
-  }
-| CALL '[' REG ']' {
-       $$ = 2;
-       op[0] = 0xC6;
-       op[1] = reg($3);
-  }
-| FCALL jmpaddr {
-       $$ = 4;
-       op[0] = 0xC4;
-       op[1] = ($2 >> 8) & 255;
-       op[2] = $2 & 255;
-       op[3] = ($2 >> 16) & 255;
-  }
-| FJMP jmpaddr {
-       $$ = 4;
-       op[0] = 0xD4;
-       op[1] = ($2 >> 8) & 255;
-       op[2] = $2 & 255;
-       op[3] = ($2 >> 16) & 255;
-  }
-| JMP '[' REG ']' {
-       $$ = 2;
-       op[0] = 0xD6;
-       op[1] = 0x70 + reg_indirect($3);
-  }
-| JMP '[' A '+' DPTR ']' {
-       $$ = 2;
-       op[0] = 0xD6;
-       op[1] = 0x46;
-  }
-| JMP '[' '[' REG '+' ']' ']' {
-       $$ = 2;
-       op[0] = 0xD6;
-       op[1] = 0x60 + reg_indirect($4);
-  }
-
-| JMP jmpaddr {
-       $$ = 3;
-       op[0] = 0xD5;
-       op[1] = msb(rel16(MEM_POS + $$, $2));
-       op[2] = lsb(rel16(MEM_POS + $$, $2));
-  }
-
-| CALL jmpaddr {
-        $$ = 3;
-        op[0] = 0xC5;
-        op[1] = msb(rel16(MEM_POS + $$, $2));
-        op[2] = lsb(rel16(MEM_POS + $$, $2));
-  }
-| branch_inst jmpaddr {
-       $$ = 2;
-       op[0] = branch_opcode;
-       op[1] = rel8(MEM_POS + $$, $2);
-  }
-| CJNE REG ',' expr ',' jmpaddr {
-        $$ = 4;
-       size = find_size1(inst_size, $2);
-       op[0] = 0xE2 + size * 8;
-       op[1] = reg($2) * 16 + msb(direct_addr($4));
-       op[2] = lsb(direct_addr($4));
-       op[3] = rel8(MEM_POS + $$, $6);
-  }
-| CJNE REG ',' '#' expr ',' jmpaddr {
-       size  = find_size1(inst_size, $2);
-       if (size == SIZE8) {
-               $$ = 4;
-               op[0] = 0xE3;
-               op[1] = reg($2) * 16;
-               op[2] = rel8(MEM_POS + $$, $7);
-               op[3] = imm_data8($5);
-       } else {
-               $$ = 5;
-               op[0] = 0xEB;
-               op[1] = reg($2) * 16;
-               op[2] = rel8(MEM_POS + $$, $7);
-               op[3] = msb(imm_data16($5));
-               op[4] = lsb(imm_data16($5));
-       }
-  }
-| CJNE '[' REG ']' ',' '#' expr ',' jmpaddr {
-       size  = find_size0(inst_size);
-       if (size == SIZE8) {
-               $$ = 4;
-               op[0] = 0xE3;
-               op[1] = reg_indirect($3) * 16 + 8;
-               op[2] = rel8(MEM_POS + $$, $9);
-               op[3] = imm_data8($7);
-       } else {
-               $$ = 5;
-               op[0] = 0xEB;
-               op[1] = reg_indirect($3) * 16 + 8;
-               op[2] = rel8(MEM_POS + $$, $9);
-               op[3] = msb(imm_data16($7));
-               op[4] = lsb(imm_data16($7));
-       }
-  }
-| DJNZ REG ',' jmpaddr {
-       $$ = 3;
-       size  = find_size1(inst_size, $2);
-       op[0] = 0x87 + size * 8;
-       op[1] = reg($2) * 16 + 8;
-       op[2] = rel8(MEM_POS + $$, $4);
-  }
-
-
-| DJNZ expr ',' jmpaddr {
-       $$ = 4;
-       size  = find_size0(inst_size);
-       op[0] = 0xE2 + size * 8;
-       op[1] = msb(direct_addr($2)) + 8;
-       op[2] = lsb(direct_addr($2));
-       op[3] = rel8(MEM_POS + $$, $4);
-  }
-
-| JB bit ',' jmpaddr {
-       $$ = 4;
-       op[0] = 0x97;
-       op[1] = 0x80 + msb(bit_addr($2));
-       op[2] = lsb(bit_addr($2));
-       op[3] = rel8(MEM_POS + $$, $4);
-  }
-
-| JBC bit ',' jmpaddr {
-       $$ = 4;
-       op[0] = 0x97;
-       op[1] = 0xC0 + msb(bit_addr($2));
-       op[2] = lsb(bit_addr($2));
-       op[3] = rel8(MEM_POS + $$, $4);
-  }
-
-| JNB bit ',' jmpaddr {
-       $$ = 4;
-       op[0] = 0x97;
-       op[1] = 0xA0 + msb(bit_addr($2));
-       op[2] = lsb(bit_addr($2));
-       op[3] = rel8(MEM_POS + $$, $4);
-  }
-
-
-arith_inst:
-         ADD   {arith_opcode = 0;}
-       | ADDC  {arith_opcode = 1;}
-       | AND   {arith_opcode = 5;}
-       | CMP   {arith_opcode = 4;}
-       | MOV   {arith_opcode = 8;}
-       | OR    {arith_opcode = 6;}
-       | SUB   {arith_opcode = 2;}
-       | SUBB  {arith_opcode = 3;}
-       | XOR   {arith_opcode = 7;}
-
-short_data_inst:
-         ADDS {short_opcode = 0xA0;}
-       | MOVS {short_opcode = 0xB0;}
-
-logical_shift_inst:
-         ASL  {shift_reg_opcode = 0xC1; shift_imm_opcode = 0xD1;}
-       | ASR  {shift_reg_opcode = 0xC2; shift_imm_opcode = 0xD2;}
-       | LSR  {shift_reg_opcode = 0xC0; shift_imm_opcode = 0xD0;}
-       | NORM {shift_reg_opcode = 0xC3; shift_imm_opcode = -1;}
-
-rotate_inst:
-         RL    {rotate_opcode = 0xD3;}
-       | RLC   {rotate_opcode = 0xD7;}
-       | RR    {rotate_opcode = 0xD0;}
-       | RRC   {rotate_opcode = 0xD7;}
-
-stack_inst:
-         POP   {stack_addr_opcode = 0x8710; stack_reg_opcode = 0x27;}
-       | POPU  {stack_addr_opcode = 0x8700; stack_reg_opcode = 0x37;}
-       | PUSH  {stack_addr_opcode = 0x8730; stack_reg_opcode = 0x07;}
-       | PUSHU {stack_addr_opcode = 0x8720; stack_reg_opcode = 0x17;}
-
-no_opperand_inst:
-         BKPT  {num_op = 1; opcode0 = 255; opcode1 = 0;}
-       | NOP   {num_op = 1; opcode0 = 0; opcode1 = 0;}
-       | RESET {num_op = 2; opcode0 = 0xD6; opcode1 = 0x10;}
-       | RET   {num_op = 2; opcode0 = 0xD6; opcode1 = 0x80;}
-       | RETI  {num_op = 2; opcode0 = 0xD6; opcode1 = 0x90;}
-
-branch_inst:
-         BCC   {branch_opcode = 0xF0;}
-       | BCS   {branch_opcode = 0xF1;}
-       | BEQ   {branch_opcode = 0xF3;}
-       | BG    {branch_opcode = 0xF8;}
-       | BGE   {branch_opcode = 0xFA;}
-       | BGT   {branch_opcode = 0xFC;}
-       | BL    {branch_opcode = 0xF9;}
-       | BLE   {branch_opcode = 0xFD;}
-       | BLT   {branch_opcode = 0xFB;}
-       | BMI   {branch_opcode = 0xF7;}
-       | BNE   {branch_opcode = 0xF2;}
-       | BNV   {branch_opcode = 0xF4;}
-       | BOV   {branch_opcode = 0xF5;}
-       | BPL   {branch_opcode = 0xF6;}
-       | BR    {branch_opcode = 0xFE;}
-       | JZ    {branch_opcode = 0xEC;}
-       | JNZ   {branch_opcode = 0xEE;}
-
-
-
-%%
-
-
-int reg(int reg_spec)
-{
-       return reg_spec & 15;
-}
-
-int reg_indirect(int reg_spec)
-{
-       if (reg_spec & BYTE_REG)
-               error("Indirect addressing may not use byte registers");
-       if ((reg_spec & 15) > 7)
-               error("Only R0 through R7 may be used for indirect addr");
-       return reg_spec & 7;
-}
-
-int rel16(int pos, int dest)
-{
-       int rel;
-
-       if (!p3) return 0;      /* don't bother unless writing code */
-       if (dest & (BRANCH_SPACING - 1))
-               error("Attempt to jump to unaligned location");
-       pos &= ~(BRANCH_SPACING - 1);
-       rel = (dest - pos) / BRANCH_SPACING;
-       if (rel < -32768 || rel > 32767)
-               error("Attempt to jump out of 16 bit relative range");
-       if (rel < 0) rel += 65536;
-       return rel;
-}
-
-int rel8(int pos, int dest)
-{
-       int rel;
-
-       if (!p3) return 0;      /* don't bother unless writing code */
-       if (dest & (BRANCH_SPACING - 1))
-               error("Attempt to jump to unaligned location");
-       pos &= ~(BRANCH_SPACING - 1);
-       rel = (dest - pos) / BRANCH_SPACING;
-       if (rel < -128 || rel > 127)
-               error("Attempt to jump out of 16 bit relative range");
-       if (rel < 0) rel += 256;
-       return rel;
-}
-
-int msb(int value)
-{
-       return (value >> 8) & 255;
-}
-
-int lsb(int value)
-{
-       return value & 255;
-}
-
-int direct_addr(int value)
-{
-       char buf[250];
-
-       if (value < 0 || value > 2047) {
-               sprintf(buf, "illegal value (%d) for direct address", value);
-               error(buf);
-       }
-       return value;
-}
-
-int imm_data4_signed(int value)
-{
-       if (value < -8 || value > 7)
-               error("illegal 4 bit (signed) value");
-       if (value >= 0) return value;
-       else return (16 + value);
-}
-
-int imm_data4_unsigned(int value)
-{
-       if (value < 0 || value > 15)
-               error("illegal 4 bit (unsigned) value");
-       return value;
-}
-
-int imm_data5_unsigned(int value)
-{
-       if (value < 0 || value > 31)
-               error("illegal 5 bit (unsigned) value");
-       return value;
-}
-
-int imm_data8(int value)
-{
-       if (value < -128 || value > 255)
-               error("illegal 8 bit value");
-       if (value >= 0) return value;
-       else return (256 + value);
-}
-
-int imm_data16(int value)
-{
-       if (value < -32728 || value > 65535)
-               error("illegal 16 bit value");
-       if (value >= 0) return value;
-       else return (65536 + value);
-}
-
-int bit_addr(int value)
-{
-       if (value < 0 || value > 1023) {
-               fprintf(stderr, "bad bit addr of 0x%04X (%d dec)\n",
-                       value, value);
-               error("illegal bit address");
-       }
-       return value;
-}
-
-
-int find_size_reg(int op1spec)
-{
-       int op1size=UNKNOWN;
-
-       if (op1spec & BYTE_REG) op1size = SIZE8;
-       if (op1spec & WORD_REG) op1size = SIZE16;
-       if (op1size == UNKNOWN)
-               error("Register without implied size");
-       return op1size;
-}
-
-int find_size0(int isize)
-{
-       if (isize == UNKNOWN)
-               error("Can't determine data size from instruction");
-       return isize;
-}
-
-int find_size1(int isize, int op1spec)
-{
-       int op1size=UNKNOWN;
-
-       if (op1spec & BYTE_REG) op1size = SIZE8;
-       if (op1spec & WORD_REG) op1size = SIZE16;
-       if (op1size == UNKNOWN)
-               error("Register without implied size");
-
-       if (isize == SIZE32 && op1size == SIZE16) return SIZE32;
-       if (isize == UNKNOWN) return op1size;
-       else {
-               if (isize != op1size)
-                       error("data size of register and inst don't agree");
-               return isize;
-       }
-}
-
-int find_size2(int isize, int op1spec, int op2spec)
-{
-       int op1size=UNKNOWN, op2size=UNKNOWN;
-
-       if (op1spec & BYTE_REG) op1size = SIZE8;
-       if (op1spec & WORD_REG) op1size = SIZE16;
-       if (op1size == UNKNOWN)
-               error("Register without implied size");
-       if (op2spec & BYTE_REG) op2size = SIZE8;
-       if (op2spec & WORD_REG) op2size = SIZE16;
-       if (op1size == UNKNOWN)
-               error("Register without implied size");
-
-       if (op1size != op2size)
-               error("data sizes of two registers don't agree");
-       if (isize == UNKNOWN) return op1size;
-       else {
-               if (isize != op1size)
-                       error("data size of registers and inst don't agree");
-               return isize;
-       }
-}
-
-
-int yyerror(char *s)
-{
-       if (yytext[0] >= 32) {
-               fprintf(stderr, "%s near '%s', line %d\n",
-                       s, yytext, lineno);
-       } else {
-               fprintf(stderr, "%s, line %d\n", s, lineno - 1);
-       }
-       return 0;
-}
-
-void error(char *s)
-{
-       yyerror(s);
-       exit(1);
-}
-
-int yywrap()
-{
-       return 1;
-}
diff --git a/as/xa51/xa_dasm.c b/as/xa51/xa_dasm.c
deleted file mode 100644 (file)
index b7d598b..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/* This file is part of Paul's XA51 Assembler, Copyright 1997,2002 Paul Stoffregen
- *
- * Paul's XA51 Assembler is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2.
- *
- * Paul's XA51 Assembler is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/* Author contact: paul@pjrc.com */
-
-
-#include <stdio.h>
-
-#define MAXHEXLINE 32  /* the maximum number of bytes to put in one line */
-
-extern FILE *fhex;  /* the file to put intel hex into */
-
-
-/* produce intel hex file output */
-
-void hexout(int byte, int memory_location, int end)
-{
-       static int byte_buffer[MAXHEXLINE];
-       static int last_mem, buffer_pos, buffer_addr;
-       static int writing_in_progress=0;
-       register int i, sum;
-
-       if (!writing_in_progress) {
-               /* initial condition setup */
-               last_mem = memory_location-1;
-               buffer_pos = 0;
-               buffer_addr = memory_location;
-               writing_in_progress = 1;
-               }
-
-       if ( (memory_location != (last_mem+1)) || (buffer_pos >= MAXHEXLINE) \
-        || ((end) && (buffer_pos > 0)) ) {
-               /* it's time to dump the buffer to a line in the file */
-               fprintf(fhex, ":%02X%04X00", buffer_pos, buffer_addr);
-               sum = buffer_pos + ((buffer_addr>>8)&255) + (buffer_addr&255);
-               for (i=0; i < buffer_pos; i++) {
-                       fprintf(fhex, "%02X", byte_buffer[i]&255);
-                       sum += byte_buffer[i]&255;
-               }
-               fprintf(fhex, "%02X\n", (-sum)&255);
-               buffer_addr = memory_location;
-               buffer_pos = 0;
-       }
-
-       if (end) {
-               fprintf(fhex, ":00000001FF\n");  /* end of file marker */
-               fclose(fhex);
-               writing_in_progress = 0;
-       }
-               
-       last_mem = memory_location;
-       byte_buffer[buffer_pos] = byte & 255;
-       buffer_pos++;
-}
-
-
index 91c70944865e0317f3d4396041260291d38d6014..31a77a832d923a31a2952c1b28aa581ecc197fdb 100644 (file)
@@ -17,6 +17,7 @@
 /* adapted from the osu8asm project, 1995 */
 /* http://www.pjrc.com/tech/osu8/index.html */
 
+#define D(x) x
 
 #include <stdio.h>
 #include <stdlib.h>
 #include "xa_main.h"
 
 extern void yyrestart(FILE *new_file);
-extern void hexout(int byte, int memory_location, int end);
 extern int yyparse();
 
 
+char modulename[PATH_MAX];
+char infilename[PATH_MAX];
+char outfilename[PATH_MAX];
+char listfilename[PATH_MAX];
+char symfilename[PATH_MAX];
+
 /* global variables */
 
-FILE *fhex, *fmem, *list_fp, *sym_fp;
+FILE *frel, *fmem, *list_fp, *sym_fp;
 extern FILE *yyin;
 extern char *yytext;
 extern char last_line_text[];
@@ -48,6 +54,7 @@ char symbol_name[1000];
 struct area_struct area[NUM_AREAS];
 int current_area=AREA_CSEG;
 
+char rel_line[2][132];
 
 char *areaToString (int area) {
   switch (area) 
@@ -80,7 +87,13 @@ struct symbol * build_sym_list(char *thename)
 {
        struct symbol *new, *p;
 
-/*     printf("  Symbol: %s  Line: %d\n", thename, lineno); */
+       if ((p=findSymbol(thename))) {
+         p->area=current_area;
+         //fprintf (stderr, "warning, symbol %s already defined\n", thename);
+         return p;
+       }
+
+       //printf("  Symbol: %s  Line: %d\n", thename, lineno);
        new = (struct symbol *) malloc(sizeof(struct symbol));
        new->name = (char *) malloc(strlen(thename)+1);
        strcpy(new->name, thename);
@@ -91,6 +104,7 @@ struct symbol * build_sym_list(char *thename)
        new->isreg = 0;
        new->line_def = lineno - 1;
        new->area = current_area;
+       new->mode = 'X'; // start with an external
        new->next = NULL;
        if (sym_list == NULL) return (sym_list = new);
        p = sym_list;
@@ -99,7 +113,17 @@ struct symbol * build_sym_list(char *thename)
        return (new);
 }
 
-int assign_value(char *thename, int thevalue)
+struct symbol *findSymbol (char *thename) {
+  struct symbol *p;
+  for (p=sym_list; p; p=p->next) {
+    if (strcasecmp(thename, p->name)==0) {
+      return p;
+    }
+  }
+  return NULL;
+}
+
+int assign_value(char *thename, int thevalue, char mode)
 {
        struct symbol *p;
 
@@ -108,6 +132,7 @@ int assign_value(char *thename, int thevalue)
                if (!(strcasecmp(thename, p->name))) {
                        p->value = thevalue;
                        p->isdef = 1;
+                       p->mode = mode;
                        return (0);
                }
                p = p->next;
@@ -116,7 +141,7 @@ int assign_value(char *thename, int thevalue)
        exit(1);
 }
 
-int mk_bit(char *thename)
+int mk_bit(char *thename, int area)
 {
         struct symbol *p;
 
@@ -124,6 +149,7 @@ int mk_bit(char *thename)
         while (p != NULL) {
                 if (!(strcasecmp(thename, p->name))) {
                         p->isbit = 1;
+                       p->area = area;
                         return (0);
                 }
                 p = p->next;
@@ -140,6 +166,7 @@ int mk_sfr(char *thename)
         while (p != NULL) {
                 if (!(strcasecmp(thename, p->name))) {
                         p->issfr = 1;
+                       p->area = 0;
                         return (0);
                 }
                 p = p->next;
@@ -251,20 +278,21 @@ void print_symbol_table()
 
 void check_redefine()
 {
-       struct symbol *p1, *p2;
-       p1 = sym_list;
-       while (p1 != NULL) {
-               p2 = p1->next;
-               while (p2 != NULL) {
-                       if (!strcasecmp(p1->name, p2->name)) {
-                               fprintf(stderr, "Error: symbol '%s' redefined on line %d", p1->name, p2->line_def);
-                               fprintf(stderr, ", first defined on line %d\n", p1->line_def);
-                       exit(1);
-                       }
-                       p2 = p2->next;
-               }
-               p1 = p1->next;
-       }
+  struct symbol *p1, *p2;
+  p1 = sym_list;
+  while (p1 != NULL) {
+    p2 = p1->next;
+    while (p2 != NULL) {
+      if (!strcasecmp(p1->name, p2->name)) {
+       fprintf(stderr, "Error: symbol '%s' redefined on line %d", 
+               p1->name, p2->line_def);
+       fprintf(stderr, ", first defined on line %d\n", p1->line_def);
+       exit(1);
+      }
+      p2 = p2->next;
+    }
+    p1 = p1->next;
+  }
 }
 
 int is_target(char *thename)
@@ -301,15 +329,27 @@ int is_reg(char *thename)
 }
 
 
-int is_def(char *thename)
+struct symbol *is_def(char *thename)
 {
-       struct symbol *p;
-       p = sym_list;
-       while (p != NULL) {
-               if (!strcasecmp(thename, p->name) && p->isdef) return(1);
-               p = p->next;
-       }
-       return (0);
+  struct symbol *p;
+  p = sym_list;
+  while (p != NULL) {
+    if (!strcasecmp(thename, p->name) && p->isdef) 
+      return p;
+    p = p->next;
+  }
+  return NULL;
+}
+
+struct symbol *is_ref(char *thename) {
+  struct symbol *p;
+  p = sym_list;
+  while (p != NULL) {
+    if (strcasecmp(thename, p->name)==0) 
+      return p;
+    p = p->next;
+  }
+  return NULL;
 }
 
 /* this routine is used to dump a group of bytes to the output */
@@ -319,33 +359,72 @@ int is_def(char *thename)
 /* though is it expected that the lexer has placed all the actual */
 /* original text from the line in "last_line_text" */
 
-void out(int *byte_list, int num)
-{
-       int i, first=1;
-
-       if (num > 0) fprintf(list_fp, "%06X: ", MEM_POS);
-       else fprintf(list_fp, "\t");
-
-       if (current_area==AREA_CSEG || current_area==AREA_XINIT) {
-         for (i=0; i<num; i++) {
-           hexout(byte_list[i], MEM_POS + i, 0);
-           if (!first && (i % 4) == 0) fprintf(list_fp, "\t");
-           fprintf(list_fp, "%02X", byte_list[i]);
-           if ((i+1) % 4 == 0) {
-             if (first) fprintf(list_fp, "\t%s\n", last_line_text);
-             else fprintf(list_fp, "\n");
-             first = 0;
-           } else {
-             if (i<num-1) fprintf(list_fp, " ");
-           }
+static short last_area=-1;
+
+int debug=0;
+
+void out(int *byte_list, int num) {
+  struct symbol *p;
+  int i, first=1;
+  
+  if (num > 0) fprintf(list_fp, "%06X: ", MEM_POS);
+  else fprintf(list_fp, "\t");
+  
+  if (last_area!=current_area) {
+    // emit area information
+    fprintf (frel, "A %s size %d flags 0\n", 
+            areaToString(current_area),
+            area[current_area].size);
+    area[current_area].defsEmitted=1;
+    if  (!area[current_area].defsEmitted) {
+      for (p=sym_list; p; p=p->next) {
+       if (p->isdef && p->area==current_area) {
+         if (debug || p->name[strlen(p->name)-1]!='$') {
+           fprintf (frel, "S %s Def%04x\n", p->name, p->value);
          }
        }
-       if (first) {
-               if (num < 3) fprintf(list_fp, "\t");
-               fprintf(list_fp, "\t%s\n", last_line_text);
-       } else {
-               if (num % 4) fprintf(list_fp, "\n");
+      }
+    }
+    last_area=current_area;
+  }
+  if (current_area==AREA_CSEG ||
+      current_area==AREA_GSFINAL ||
+      current_area==AREA_XINIT) {
+    if (num) {
+      fprintf (frel, "T %02x %02x", (MEM_POS>>16)&0xff, MEM_POS&0xff);
+      for (i=0; i<num; i++) {
+       fprintf (frel, " %02x", byte_list[i]);
+      }
+      fprintf (frel, "\n");
+      if (rel_line[0][0]) {
+       fprintf (frel, "%s\n", rel_line[0]);
+       if (rel_line[1][0]) {
+         fprintf (frel, "%s\n", rel_line[1]);
        }
+      }
+    }
+    for (i=0; i<num; i++) {
+      if (!first && (i % 4) == 0) fprintf(list_fp, "\t");
+      fprintf(list_fp, "%02X", byte_list[i]);
+      if ((i+1) % 4 == 0) {
+       if (first) fprintf(list_fp, "\t%s\n", last_line_text);
+       else fprintf(list_fp, "\n");
+       first = 0;
+      } else {
+       if (i<num-1) fprintf(list_fp, " ");
+      }
+    }
+  }
+  if (first) {
+    if (num < 3) fprintf(list_fp, "\t");
+    fprintf(list_fp, "\t%s\n", last_line_text);
+  } else {
+    if (num % 4) fprintf(list_fp, "\n");
+  }
+  expr_var[0][0]='\0';
+  expr_var[1][0]='\0';
+  rel_line[0][0]='\0';
+  rel_line[1][0]='\0';
 }
 
 
@@ -429,16 +508,36 @@ void init_areas(void)
 }
 
 void addAreaSymbols() {
-  char buffer[132];
-  int i;
+  //char buffer[132];
+  int i, areas=0, globals=0;
+  struct symbol *p;
+
+  fprintf (frel, "XH\n");
   for (i=0; i<NUM_AREAS; i++) {
+    if ((area[i].size=area[i].alloc_position-area[i].start)) {
+      areas++;
+    }
+#if 0
     current_area=i;
     sprintf (buffer, "s_%s", areaToString(i));
     build_sym_list (buffer);
-    assign_value (buffer, area[i].start);
     buffer[0]='l';
     build_sym_list (buffer);
-    assign_value (buffer, area[i].alloc_position-area[i].start);
+#endif
+  }
+  for (p=sym_list; p; p=p->next) {
+    if (p->isdef) {
+      if (debug || p->name[strlen(p->name)-1]!='$') {
+       globals++;
+      }
+    }
+  }
+  fprintf (frel, "H %d areas %d global symbols\n", areas, globals);
+  fprintf (frel, "M %s\n", modulename);
+  for (p=sym_list; p; p=p->next) {
+    if (!p->isdef) {
+      fprintf (frel, "S %s Ref0000\n", p->name);
+    }
   }
 }
 
@@ -453,12 +552,6 @@ void printVersion() {
   printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
 }
 
-char infilename[PATH_MAX];
-char outfilename[PATH_MAX];
-char listfilename[PATH_MAX];
-char symfilename[PATH_MAX];
-//char mapfilename[PATH_MAX];
-
 int verbose=0, createSymbolFile=0;
 
 void process_args(int argc, char **argv) 
@@ -498,17 +591,13 @@ void process_args(int argc, char **argv)
     print_usage(1);
   }
 
-  strcpy(outfilename, infilename);
-  outfilename[strlen(outfilename)-3] = '\0';
-  strcpy(listfilename, outfilename);
+  strcpy(modulename, infilename);
+  modulename[strlen(modulename)-3] = '\0';
+  sprintf (outfilename, "%s.rel", modulename);
+  sprintf (listfilename, "%s.lst", modulename);
   if (createSymbolFile) {
-    strcpy(symfilename, outfilename);
-    strcat(symfilename, ".sym");
+    sprintf (symfilename, "%s.sym", modulename);
   }
-  //strcpy(mapfilename, outfilename);
-  strcat(outfilename, ".hex");
-  strcat(listfilename, ".lst");
-  //strcat(mapfilename, ".map");
 }
 
 /* pass #1 (p1=1) find all symbol defs and branch target names */
@@ -524,8 +613,8 @@ int main(int argc, char **argv)
                fprintf(stderr, "Can't open file '%s'.\n", infilename);
                exit(1);
        }
-       fhex = fopen(outfilename, "w");
-       if (fhex == NULL) {
+       frel = fopen(outfilename, "w");
+       if (frel == NULL) {
                fprintf(stderr, "Can't write file '%s'.\n", outfilename);
                exit(1);
        }
@@ -571,7 +660,6 @@ int main(int argc, char **argv)
        yyparse();
 
        fclose(yyin);
-       hexout(0, 0, 1);  /* flush and close intel hex file output */
        return 0;
 }
 
index 2daf30e37bf7261e66843ca08f0ebcf3c1dedd2e..d95f57a20e7a83c6c3319b2dde93cfb1aab80c4e 100644 (file)
@@ -34,7 +34,9 @@ struct symbol {
         int isbit;      /* 1 if a bit address, 0 otherwise */
         int issfr;
        int isreg;      /* 1 if a register, 0 otehrwise */
-  int area;       /* the area that this symbol is in */
+        char mode;      /* Absolute, Relative, Tmplabel, eXternal */
+        short lk_index; /* symbol index for the linker */
+        int area;       /* the area that this symbol is in */
         struct symbol *next; };
 
 /* a list of all the symbols that are branch targets */
@@ -47,6 +49,8 @@ struct target {
 struct area_struct {
         int start;
        int alloc_position;
+        int defsEmitted;
+        int size;
 };
 
 extern int current_area;
@@ -54,7 +58,7 @@ extern int current_area;
 #define MEM_POS (area[current_area].alloc_position)
 
 enum {
-  AREA_CSEG=0,
+  AREA_CSEG=1,
   AREA_DSEG,
   // AREA_OSEG,
   // AREA_ISEG,
@@ -66,7 +70,7 @@ enum {
   AREA_GSFINAL,
   AREA_HOME,
   AREA_SSEG,
-  NUM_AREAS
+  NUM_AREAS=AREA_SSEG
 };
 
 extern struct area_struct area[NUM_AREAS];
@@ -77,13 +81,46 @@ extern int lineno;
 extern int p1, p2, p3, mem, m_len;
 
 extern struct symbol * build_sym_list(char *thename);
-extern int assign_value(char *thename, int thevalue);
-extern int mk_bit(char *thename);
+extern int assign_value(char *thename, int thevalue, char mode);
+extern int mk_bit(char *thename, int current_area);
 extern int mk_reg(char *thename);
 extern void out(int *byte_list, int num);
 extern int is_target(char *thename);
 extern void pad_with_nop();
 extern int binary2int(char *str);
-extern int is_def(char *thename);
+extern int is_bit(char *thename);
+extern int is_reg(char *thename);
+extern struct symbol * is_def(char *thename);
+extern struct symbol * is_ref(char *thename);
 extern int get_value(char *thename);
-
+extern struct symbol *findSymbol (char *thename);
+extern char rel_line[2][132];
+extern char expr_var[2][MAX_SYMBOL];
+extern void error(char*);
+int mk_bit(char*, int);
+int mk_sfr(char*);
+struct target * build_target_list(char *thename);
+struct symbol * build_sym_list(char *);
+int find_size_reg(int op1spec);
+int find_size0(int isize);
+int find_size1(int isize, int op1spec);
+int find_size2(int isize, int op1spec, int op2spec);
+int yyerror(char *s);
+int imm_data4_signed(int value);
+int imm_data4_unsigned(int value);
+int imm_data5_unsigned(int value);
+int imm_data8(int value);
+int imm_data16(int value);
+int reg(int reg_spec);
+int reg_indirect(int reg_spec);
+int lsb(int value);
+int msb(int value);
+int direct_addr(int value);
+int bit_addr(int value);
+int rel16(int pos, int dest);
+int rel8(int pos, int dest);
+char *areaToString (int area);
+
+FILE *frel, *fmem, *list_fp, *sym_fp;
+
+extern void relout();
diff --git a/as/xa51/xa_rasm.l b/as/xa51/xa_rasm.l
new file mode 100755 (executable)
index 0000000..3f35c18
--- /dev/null
@@ -0,0 +1,326 @@
+%{
+/* This file is part of Paul's XA51 Assembler, Copyright 1997,2002 Paul Stoffregen
+ *
+ * Paul's XA51 Assembler is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2.
+ *
+ * Paul's XA51 Assembler is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* Author contact: paul@pjrc.com */
+
+#include <stdio.h>
+#include <string.h>
+#include "xa_main.h"
+#include "xa_rasm.tab.h"
+
+extern int inst_size, yylval;
+char line_text[MAX_LINE]={'\0'}, last_line_text[MAX_LINE];
+char lex_sym_name[MAX_SYMBOL];
+extern char base_symbol_name[];
+#define LIST if (p3) strcat(line_text, yytext)
+%}
+
+%%
+
+add\.w         {LIST; inst_size=SIZE16; return ADD;}
+add\.b         {LIST; inst_size=SIZE8; return ADD;}
+add            {LIST; inst_size=UNKNOWN; return ADD;}
+addc\.w                {LIST; inst_size=SIZE16; return ADDC;}
+addc\.b                {LIST; inst_size=SIZE8; return ADDC;}
+addc           {LIST; inst_size=UNKNOWN; return ADDC;}
+adds\.w                {LIST; inst_size=SIZE16; return ADDS;}
+adds\.b                {LIST; inst_size=SIZE8; return ADDS;}
+adds           {LIST; inst_size=UNKNOWN; return ADDS;}
+and\.w         {LIST; inst_size=SIZE16; return AND;}
+and\.b         {LIST; inst_size=SIZE8; return AND;}
+and            {LIST; inst_size=UNKNOWN; return AND;}
+anl            {LIST; inst_size=UNKNOWN; return ANL;}
+asl\.d         {LIST; inst_size=SIZE32; return ASL;}
+asl\.w         {LIST; inst_size=SIZE16; return ASL;}
+asl\.b         {LIST; inst_size=SIZE8; return ASL;}
+asl            {LIST; inst_size=UNKNOWN; return ASL;}
+asr\.d         {LIST; inst_size=SIZE32; return ASR;}
+asr\.w         {LIST; inst_size=SIZE16; return ASR;}
+asr\.b         {LIST; inst_size=SIZE8; return ASR;}
+asr            {LIST; inst_size=UNKNOWN; return ASR;}
+bcc            {LIST; inst_size=UNKNOWN; return BCC;}
+bcs            {LIST; inst_size=UNKNOWN; return BCS;}
+beq            {LIST; inst_size=UNKNOWN; return BEQ;}
+bg             {LIST; inst_size=UNKNOWN; return BG;}
+bge            {LIST; inst_size=UNKNOWN; return BGE;}
+bgt            {LIST; inst_size=UNKNOWN; return BGT;}
+bkpt           {LIST; inst_size=UNKNOWN; return BKPT;}
+bl             {LIST; inst_size=UNKNOWN; return BL;}
+ble            {LIST; inst_size=UNKNOWN; return BLE;}
+blt            {LIST; inst_size=UNKNOWN; return BLT;}
+bmi            {LIST; inst_size=UNKNOWN; return BMI;}
+bne            {LIST; inst_size=UNKNOWN; return BNE;}
+bnv            {LIST; inst_size=UNKNOWN; return BNV;}
+bov            {LIST; inst_size=UNKNOWN; return BOV;}
+bpl            {LIST; inst_size=UNKNOWN; return BPL;}
+br             {LIST; inst_size=UNKNOWN; return BR;}
+call           {LIST; inst_size=UNKNOWN; return CALL;}
+cjne\.w                {LIST; inst_size=SIZE16; return CJNE;}
+cjne\.b                {LIST; inst_size=SIZE8; return CJNE;}
+cjne           {LIST; inst_size=UNKNOWN; return CJNE;}
+clr            {LIST; inst_size=UNKNOWN; return CLR;}
+cmp\.w         {LIST; inst_size=SIZE16; return CMP;}
+cmp\.b         {LIST; inst_size=SIZE8; return CMP;}
+cmp            {LIST; inst_size=UNKNOWN; return CMP;}
+cpl\.w         {LIST; inst_size=SIZE16; return CPL;}
+cpl\.b         {LIST; inst_size=SIZE8; return CPL;}
+cpl            {LIST; inst_size=UNKNOWN; return CPL;}
+da\.b          {LIST; inst_size=SIZE8; return DA;}
+da             {LIST; inst_size=UNKNOWN; return DA;}
+div\.d         {LIST; inst_size=SIZE32; return DIV;}
+div\.w         {LIST; inst_size=SIZE16; return DIV;}
+div\.b         {LIST; inst_size=SIZE8; return DIV;}
+div            {LIST; inst_size=UNKNOWN; return DIV;}
+divu\.d                {LIST; inst_size=SIZE32; return DIVU;}
+divu\.w                {LIST; inst_size=SIZE16; return DIVU;}
+divu\.b                {LIST; inst_size=SIZE8; return DIVU;}
+divu           {LIST; inst_size=UNKNOWN; return DIVU;}
+djnz\.w                {LIST; inst_size=SIZE16; return DJNZ;}
+djnz\.b                {LIST; inst_size=SIZE8; return DJNZ;}
+djnz           {LIST; inst_size=UNKNOWN; return DJNZ;}
+fcall          {LIST; inst_size=UNKNOWN; return FCALL;}
+fjmp           {LIST; inst_size=UNKNOWN; return FJMP;}
+jb             {LIST; inst_size=UNKNOWN; return JB;}
+jbc            {LIST; inst_size=UNKNOWN; return JBC;}
+jmp            {LIST; inst_size=UNKNOWN; return JMP;}
+jnb            {LIST; inst_size=UNKNOWN; return JNB;}
+jnz            {LIST; inst_size=UNKNOWN; return JNZ;}
+jz             {LIST; inst_size=UNKNOWN; return JZ;}
+lea\.w         {LIST; inst_size=SIZE16; return LEA;}
+lea            {LIST; inst_size=UNKNOWN; return LEA;}
+lsr\.d         {LIST; inst_size=SIZE32; return LSR;}
+lsr\.w         {LIST; inst_size=SIZE16; return LSR;}
+lsr\.b         {LIST; inst_size=SIZE8; return LSR;}
+lsr            {LIST; inst_size=UNKNOWN; return LSR;}
+mov\.w         {LIST; inst_size=SIZE16; return MOV;}
+mov\.b         {LIST; inst_size=SIZE8; return MOV;}
+mov            {LIST; inst_size=UNKNOWN; return MOV;}
+movc\.w                {LIST; inst_size=SIZE16; return MOVC;}
+movc\.b                {LIST; inst_size=SIZE8; return MOVC;}
+movc           {LIST; inst_size=UNKNOWN; return MOVC;}
+movs\.w                {LIST; inst_size=SIZE16; return MOVS;}
+movs\.b                {LIST; inst_size=SIZE8; return MOVS;}
+movs           {LIST; inst_size=UNKNOWN; return MOVS;}
+movx\.w                {LIST; inst_size=SIZE16; return MOVX;}
+movx\.b                {LIST; inst_size=SIZE8; return MOVX;}
+movx           {LIST; inst_size=UNKNOWN; return MOVX;}
+mul\.d         {LIST; inst_size=SIZE32; return MUL;}
+mul\.w         {LIST; inst_size=SIZE16; return MUL;}
+mul\.b         {LIST; inst_size=SIZE8; return MUL;}
+mul            {LIST; inst_size=UNKNOWN; return MUL;}
+mulu\.d                {LIST; inst_size=SIZE32; return MULU;}
+mulu\.w                {LIST; inst_size=SIZE16; return MULU;}
+mulu\.b                {LIST; inst_size=SIZE8; return MULU;}
+mulu           {LIST; inst_size=UNKNOWN; return MULU;}
+neg\.w         {LIST; inst_size=SIZE16; return NEG;}
+neg\.b         {LIST; inst_size=SIZE8; return NEG;}
+neg            {LIST; inst_size=UNKNOWN; return NEG;}
+nop            {LIST; inst_size=UNKNOWN; return NOP;}
+norm\.d                {LIST; inst_size=SIZE32; return NORM;}
+norm\.w                {LIST; inst_size=SIZE16; return NORM;}
+norm\.b                {LIST; inst_size=SIZE8; return NORM;}
+norm           {LIST; inst_size=UNKNOWN; return NORM;}
+or\.w          {LIST; inst_size=SIZE16; return OR;}
+or\.b          {LIST; inst_size=SIZE8; return OR;}
+or             {LIST; inst_size=UNKNOWN; return OR;}
+orl            {LIST; inst_size=UNKNOWN; return ORL;}
+pop\.w         {LIST; inst_size=SIZE16; return POP;}
+pop\.b         {LIST; inst_size=SIZE8; return POP;}
+pop            {LIST; inst_size=UNKNOWN; return POP;}
+popu\.w                {LIST; inst_size=SIZE16; return POPU;}
+popu\.b                {LIST; inst_size=SIZE8; return POPU;}
+popu           {LIST; inst_size=UNKNOWN; return POPU;}
+push\.w                {LIST; inst_size=SIZE16; return PUSH;}
+push\.b                {LIST; inst_size=SIZE8; return PUSH;}
+push           {LIST; inst_size=UNKNOWN; return PUSH;}
+pushu\.w       {LIST; inst_size=SIZE16; return PUSHU;}
+pushu\.b       {LIST; inst_size=SIZE8; return PUSHU;}
+pushu          {LIST; inst_size=UNKNOWN; return PUSHU;}
+reset          {LIST; inst_size=UNKNOWN; return RESET;}
+ret            {LIST; inst_size=UNKNOWN; return RET;}
+reti           {LIST; inst_size=UNKNOWN; return RETI;}
+rl\.w          {LIST; inst_size=SIZE16; return RL;}
+rl\.b          {LIST; inst_size=SIZE8; return RL;}
+rl             {LIST; inst_size=UNKNOWN; return RL;}
+rlc\.w         {LIST; inst_size=SIZE16; return RLC;}
+rlc\.b         {LIST; inst_size=SIZE8; return RLC;}
+rlc            {LIST; inst_size=UNKNOWN; return RLC;}
+rr\.w          {LIST; inst_size=SIZE16; return RR;}
+rr\.b          {LIST; inst_size=SIZE8; return RR;}
+rr             {LIST; inst_size=UNKNOWN; return RR;}
+rrc\.w         {LIST; inst_size=SIZE16; return RRC;}
+rrc\.b         {LIST; inst_size=SIZE8; return RRC;}
+rrc            {LIST; inst_size=UNKNOWN; return RRC;}
+setb           {LIST; inst_size=UNKNOWN; return SETB;}
+sext\.w                {LIST; inst_size=SIZE16; return SEXT;}
+sext\.b                {LIST; inst_size=SIZE8; return SEXT;}
+sext           {LIST; inst_size=UNKNOWN; return SEXT;}
+sub\.w         {LIST; inst_size=SIZE16; return SUB;}
+sub\.b         {LIST; inst_size=SIZE8; return SUB;}
+sub            {LIST; inst_size=UNKNOWN; return SUB;}
+subb\.w                {LIST; inst_size=SIZE16; return SUBB;}
+subb\.b                {LIST; inst_size=SIZE8; return SUBB;}
+subb           {LIST; inst_size=UNKNOWN; return SUBB;}
+trap           {LIST; inst_size=UNKNOWN; return TRAP;}
+xch\.w         {LIST; inst_size=SIZE16; return XCH;}
+xch\.b         {LIST; inst_size=SIZE8; return XCH;}
+xch            {LIST; inst_size=UNKNOWN; return XCH;}
+xor\.w         {LIST; inst_size=SIZE16; return XOR;}
+xor\.b         {LIST; inst_size=SIZE8; return XOR;}
+xor            {LIST; inst_size=UNKNOWN; return XOR;}
+
+
+dptr           {LIST; return DPTR;}
+pc             {LIST; return PC;}
+a              {LIST; return A;}
+c              {LIST; return C;}
+usp            {LIST; return USP;}
+
+org            {LIST; return ORG;}
+equ            {LIST; return EQU;}
+sfr            {LIST; return SFR;}
+db             {LIST; return DB;}
+dw             {LIST; return DW;}
+byte           {LIST; return DB;}
+bit            {LIST; return BITDEF;}
+reg            {LIST; return REGDEF;}
+area           {LIST; return AREA;}
+ds             {LIST; return DS;}
+DSEG           {LIST; yylval = AREA_DSEG; return AREA_NAME;}
+BSEG           {LIST; yylval = AREA_BSEG; return AREA_NAME;}
+XSEG           {LIST; yylval = AREA_XSEG; return AREA_NAME;}
+XISEG          {LIST; yylval = AREA_XISEG; return AREA_NAME;}
+XINIT          {LIST; yylval = AREA_XINIT; return AREA_NAME;}
+GSINIT         {LIST; yylval = AREA_GSINIT; return AREA_NAME;}
+GSFINAL                {LIST; yylval = AREA_GSFINAL; return AREA_NAME;}
+HOME           {LIST; yylval = AREA_HOME; return AREA_NAME;}
+SSEG            {LIST; yylval = AREA_SSEG; return AREA_NAME;}
+CSEG           {LIST; yylval = AREA_CSEG; return AREA_NAME;}
+module         {LIST; return MODULE;}
+globl          {LIST; return GLOBL;}
+\(DATA\)       {LIST; return AREA_DESC;}
+\(OVR,XDATA\)  {LIST; return AREA_DESC;}
+\(BIT\)                {LIST; return AREA_DESC;}
+\(XDATA\)      {LIST; return AREA_DESC;}
+\(CODE\)       {LIST; return AREA_DESC;}
+low            {LIST; return LOW;}
+high           {LIST; return HIGH;}
+>>             {LIST; return RSHIFT;}
+\<\<           {LIST; return LSHIFT;}
+
+R[0-9]         {LIST; yylval = yytext[1] - '0' + WORD_REG; return REG;}
+R1[0-5]                {LIST; yylval = yytext[2] - '0' + 10 + WORD_REG; return REG;}
+R[0-7]L                {LIST; yylval = (yytext[1] - '0') * 2 + BYTE_REG; return REG;}
+R[0-7]H                {LIST; yylval = (yytext[1] - '0') * 2 + 1 + BYTE_REG; return REG;}
+
+
+[a-z_][a-z0-9_]*       {
+                               LIST;
+                               if (is_def(yytext)) {
+                                       yylval = get_value(yytext);
+                               } else {
+                                        if (p1) build_sym_list(yytext);
+                                       yylval = 0;
+                                        //if (p3) error("Symbol undefined");
+                               }
+                               /* keep name in lex_sym_name since yytext */
+                               /* could be overwritten if the parser does */
+                               /* a lookahead operation */
+                               strcpy(lex_sym_name, yytext);
+                               if (is_def(lex_sym_name)) {
+                                       yylval = get_value(lex_sym_name);
+                                       /* return correct type if special */
+                                       if (is_bit(lex_sym_name)) return BIT;
+                                       if (is_reg(lex_sym_name)) return REG;
+                               }
+                               return WORD;
+                       }
+[0-9]+\$               {
+                               LIST;
+                               /* should print error if base_symbol_name */
+                               /* is not defined */
+                               sprintf(lex_sym_name, "%s:%s",
+                                       base_symbol_name, yytext);
+                               if (is_def(lex_sym_name)) {
+                                       yylval = get_value(lex_sym_name);
+                               } else {
+                                       yylval = 0;
+                                       if (p3) error("Symbol undefined");
+                               }
+                               return WORD;
+                       }
+[01]+[bq]              {
+                               LIST;
+                               yylval = binary2int(yytext);
+                               return NUMBER;
+                       }
+0x[0-9a-f]+            {
+                               LIST;
+                               sscanf(yytext, "%*c%*c%x", &yylval);
+                               return NUMBER;
+                       }
+[0-9a-f]+[h]           {
+                               LIST;
+                               sscanf(yytext, "%x%*[hH]", &yylval);
+                               return NUMBER;
+                       }
+\$[0-9a-f]+            {
+                               LIST;
+                               sscanf(yytext, "$%x", &yylval);
+                               return NUMBER;
+                       }
+-?[0-9]+               {
+                               LIST;
+                               sscanf(yytext, "%d", &yylval);
+                               return NUMBER;
+                       }
+\'.\'                  {
+                               LIST;
+                               yylval = (int)yytext[1];
+                               return CHAR;
+                       }
+\'\\.\'                        {
+                               LIST;
+                               switch (yytext[1]) {
+                                       case 'n':
+                                       case 'N': yylval = 10; break;
+                                       case 'r':
+                                       case 'R': yylval = 13; break;
+                                       case '0': yylval = 0; break;
+                                       default:  yylval = (int)yytext[1];
+                                       /* print a warning here */
+                               }
+                               return CHAR;
+                       }
+\"[^"\n]*["\n]         {
+                               LIST;
+                               return STRING;
+                       }
+
+;[^\n]*                {LIST; /* comments */}
+[ \t\r]                {LIST; /* whitespace */}
+
+\n             {
+                       strcpy(last_line_text, line_text);
+                       line_text[0] = '\0';
+                       ++lineno;
+                       return EOL;
+               }
+
+.              {LIST; return yytext[0];}
+
+%%
diff --git a/as/xa51/xa_rasm.y b/as/xa51/xa_rasm.y
new file mode 100755 (executable)
index 0000000..03ade71
--- /dev/null
@@ -0,0 +1,1505 @@
+%{
+/* This file is part of Paul's XA51 Assembler, Copyright 1997,2002 Paul Stoffregen
+ *
+ * Paul's XA51 Assembler is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2.
+ *
+ * Paul's XA51 Assembler is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* Author contact: paul@pjrc.com */
+
+/* parser for the 51-XA assembler, Paul Stoffregen, July 1997 */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "xa_main.h"
+  
+int op[MAX_DB];
+int size;
+int inst_size;
+int arith_opcode, short_opcode, num_op, opcode0, opcode1;
+int shift_imm_opcode, shift_reg_opcode, rotate_opcode;
+int stack_addr_opcode, stack_reg_opcode, branch_opcode;
+int rlist_reg_bank, rlist_bitmask, rlist_size;
+int db_count, dw_count, i;
+char symbol_name[MAX_SYMBOL], base_symbol_name[MAX_SYMBOL]={'\0'};
+char expr_var[2][MAX_SYMBOL]={{'\0'},{'\0'}};
+
+extern char lex_sym_name[];
+extern int yylex();
+
+extern void yyrestart(FILE *new_file);
+extern char * disasm(int byte, int memory_location);
+void error(char *s);
+
+
+void RELOC_FF(unsigned pc, unsigned short offset, short rl) {
+  struct symbol *sym;
+  if ((sym=findSymbol(yytext))) {
+    if (sym->mode=='X') {
+      sprintf (rel_line[rl], "R %d REL_FF 0x%04x %s", offset, pc,
+              sym->name);
+    }
+  }
+}
+void RELOC_FFFF(unsigned pc, unsigned short offset, short rl) {
+  struct symbol *sym;
+  if ((sym=findSymbol(yytext))) {
+    if (sym->mode=='X') {
+      sprintf (rel_line[rl], "R %d REL_FFFF 0x%04x %s", offset, pc,
+              sym->name);
+    }
+  }
+}
+void RELOC_ABS_0F(unsigned short offset, int expr) {
+  struct symbol *sym;
+  if ((sym=findSymbol(expr_var[expr]))) {
+    if (sym->mode=='X') {
+      sprintf (rel_line[expr], "R %d ABS_0F %s", offset, sym->name);
+    }
+  }
+}
+
+void RELOC_ABS_FF(unsigned short offset, int expr) {
+  struct symbol *sym;
+  if ((sym=findSymbol(expr_var[expr]))) {
+    if (sym->mode=='X') {
+      sprintf (rel_line[expr], "R %d ABS_FF %s", offset, sym->name);
+    }
+  }
+}
+
+void RELOC_ABS_03FF(unsigned short offset, int expr) {
+  struct symbol *sym;
+  if (expr_var[0]) {
+    if ((sym=findSymbol(expr_var[expr]))) {
+      if (sym->mode=='X') {
+       sprintf (rel_line[expr], "R %d ABS_03FF %s", offset, sym->name);
+      }
+    }
+  }
+}
+
+void RELOC_ABS_07ff(unsigned short offset, int expr) {
+  struct symbol *sym;
+  if (expr_var[0]) {
+    if ((sym=findSymbol(expr_var[expr]))) {
+      if (sym->mode=='X') {
+       sprintf (rel_line[expr], "R %d ABS_07ff %s", offset, sym->name);
+      }
+    }
+  }
+}
+
+void RELOC_ABS_F0FF(unsigned short offset, int expr) {
+  struct symbol *sym;
+  if (expr_var[0]) {
+    if ((sym=findSymbol(expr_var[expr]))) {
+      if (sym->mode=='X') {
+       sprintf (rel_line[expr], "R %d ABS_F0FF %s", offset, sym->name);
+      }
+    }
+  }
+}
+void RELOC_ABS_FFFF(unsigned short offset, int expr) {
+  struct symbol *sym;
+  if (expr_var[0]) {
+    if ((sym=findSymbol(expr_var[expr]))) {
+      if (sym->mode=='X') {
+#if 1
+       sprintf (rel_line[expr], "R %d ABS_FFFF %s", offset, sym->name);
+#else
+       sprintf (rel_line[expr], "R 0 0 00 %02x 02 %02x %02x", current_area, 
+                (sym->lk_index>>8)&0xff, sym->lk_index&&0xff);
+#endif
+      }
+    }
+  }
+}
+void RELOC_ABS_0F00FF(unsigned short offset, int expr) {
+  struct symbol *sym;
+  if (expr_var[0]) {
+    if ((sym=findSymbol(expr_var[expr]))) {
+      if (sym->mode=='X') {
+       sprintf (rel_line[expr], "R %d ABS_0F00FF %s", offset, sym->name);
+      }
+    }
+  }
+}
+%}
+
+%token ADD ADDC ADDS AND ANL ASL ASR BCC BCS BEQ BG BGE BGT
+%token BKPT BL BLE BLT BMI BNE BNV BOV BPL BR CALL CJNE CLR
+%token CMP CPL DA DIV DIVU DJNZ FCALL FJMP JB JBC JMP JNB JNZ
+%token JZ LEA LSR MOV MOVC MOVS MOVX MUL MULU NEG NOP NORM
+%token OR ORL POP POPU PUSH PUSHU RESET RET RETI RL RLC RR RRC
+%token SETB SEXT SUB SUBB TRAP XCH XOR
+%token REG DPTR PC A C USP
+%token WORD BIT NUMBER CHAR STRING EOL LOCAL_LABEL
+%token ORG EQU SFR DB DW BITDEF REGDEF LOW HIGH
+%token RSHIFT LSHIFT
+%token AREA AREA_NAME AREA_DESC DS
+%token MODULE GLOBL 
+
+%left '&' '|' '^'
+%left RSHIFT LSHIFT
+%left '+' '-'
+%left '*' '/'
+%nonassoc UNARY
+
+%%
+
+all:           line
+             | line all;
+
+line:          linesymbol ':' linenosym {
+                       if (p1) {
+                               build_sym_list(symbol_name);
+                               if (current_area == AREA_BSEG) {
+                                       mk_bit(symbol_name, current_area);
+                               }
+                       }
+                       if (p1 || p2) assign_value(symbol_name, MEM_POS, 'R');
+                       MEM_POS += $3;
+               }
+             | linenosym {
+                       MEM_POS += $1;
+               }
+
+linenosym:     directive EOL {
+                       if (p3) out(op, $1);
+                       $$ = $1;
+               }
+             | instruction EOL {
+                       if (p3) out(op, $1);
+                       $$ = $1;
+               }
+            | EOL {
+                       if (p3) out(NULL, 0);
+                       $$ = 0;
+               }
+            | error EOL        /* try to recover from any parse error */
+
+
+directive:     '.' ORG expr {
+                       MEM_POS = $3;
+                       $$ = 0;
+               }
+            | ORG expr {
+                       MEM_POS = $2;
+                       $$ = 0;
+               }
+             | '.' EQU symbol ',' expr { 
+                       if (p1) build_sym_list(symbol_name);
+                       if (p1 || p2) assign_value(symbol_name, $5, '?');
+                       $$ = 0;
+               }
+             | normal_or_bit_symbol '=' expr {
+                       if (p1) build_sym_list(symbol_name);
+                       if (p1 || p2) assign_value(symbol_name, $3, '?');
+               }
+            | symbol SFR expr {
+                       if (p1) build_sym_list(symbol_name);
+                       if (p1 || p2) assign_value(symbol_name, $3, 'A');
+                       if (p1 || p2) mk_sfr(symbol_name);
+                       $$ = 0;
+               }
+            | '.' BITDEF bitsymbol ',' bit {
+                       if (p1) {
+                               build_sym_list(symbol_name);
+                               mk_bit(symbol_name, 0);
+                       }
+                       if (p1 || p2) assign_value(symbol_name, $5, '?');
+                       $$ = 0;
+               }
+            | bitsymbol BITDEF bit {
+                       if (p1) {
+                                build_sym_list(symbol_name);
+                                mk_bit(symbol_name, 0);
+                        }
+                        if (p1 || p2) assign_value(symbol_name, $3, '?');
+                        $$ = 0;
+                }
+            | bitsymbol BITDEF expr {
+                       if (p1) {
+                                build_sym_list(symbol_name);
+                                mk_bit(symbol_name, 0);
+                        }
+                        if (p1 || p2) assign_value(symbol_name, $3, 'A');
+                        $$ = 0;
+                }
+            | '.' REGDEF regsymbol ',' REG {
+                       if (p1) {
+                               build_sym_list(symbol_name);
+                               mk_reg(symbol_name);
+                       }
+                       if (p1 || p2) assign_value(symbol_name, $5, '?');
+                       $$ = 0;
+               }
+            | regsymbol REGDEF REG {
+                       if (p1) {
+                                build_sym_list(symbol_name);
+                                mk_reg(symbol_name);
+                        }
+                        if (p1 || p2) assign_value(symbol_name, $3, '?');
+                        $$ = 0;
+                }
+
+             | '.' db_directive bytes {
+                       $$ = db_count;
+               }
+            | '.' dw_directive words {
+                       $$ = dw_count;
+               }
+            | '.' AREA AREA_NAME AREA_DESC {
+                       if ($3 < 0 || $3 > NUM_AREAS) {
+                               error("Illegal Area Directive");
+                       }
+                       symbol_name[0] = '\0';
+                       current_area = $3;
+                       $$ = 0;
+               }
+            | '.' MODULE WORD {
+                       /* ignore module definition */
+                       $$ = 0;
+               }
+            | '.' GLOBL WORD {
+                       /* ignore global symbol declaration */
+                       $$ = 0;
+               }
+            | '.' GLOBL bit {
+                       /* ignore bit symbol declaration */
+                       $$ = 0;
+               }
+            | '.' DS expr {
+                       /* todo: if CSEG, emit some filler bytes */
+                       $$ = $3;
+               }
+
+db_directive:  DB {db_count = 0;}
+
+
+linesymbol:    normal_or_bit_symbol  { 
+                       strcpy(symbol_name, lex_sym_name);
+                       if (!strchr(lex_sym_name, ':')) {
+                               /* non-local label, remember base name */
+                               strcpy(base_symbol_name, lex_sym_name);
+                       }
+                       if (is_target(symbol_name)) pad_with_nop();
+               }
+
+normal_or_bit_symbol: WORD {$$ = $1;}
+               | BIT {$$ = $1;}
+
+bytes:           byte_element
+               | bytes ',' byte_element
+
+byte_element:  expr {
+                       op[db_count] = $1 & 255;
+                       if (++db_count >= MAX_DB) {
+                               error("too many bytes, use two DB");
+                               db_count--;
+                       }
+               }
+               | STRING {
+                       for(i=1; i < strlen(yytext)-1; i++) {
+                               op[db_count++] = yytext[i];
+                               if (db_count >= MAX_DB) {
+                                       error("too many bytes, use two DB");
+                                       db_count--;
+                               }
+                       }
+               }
+
+dw_directive:  DW {dw_count = 0;}
+
+words:           words ',' word_element
+               | word_element
+
+word_element:  expr {
+                       op[dw_count] = $1 & 255;
+                       op[dw_count+1] = ($1 >> 8) & 255;
+                       dw_count += 2;
+                       if (dw_count >= MAX_DB) {
+                               error("too many bytes, use two DW");
+                               db_count -= 2;
+                       }
+               }
+
+
+
+symbol:     WORD  {
+               strcpy(symbol_name, lex_sym_name);
+               }
+
+bitsymbol:    WORD { strcpy(symbol_name, lex_sym_name); }
+           | BIT  { strcpy(symbol_name, lex_sym_name); }
+
+
+regsymbol:    WORD { strcpy(symbol_name, lex_sym_name); }
+           | REG  { strcpy(symbol_name, lex_sym_name); }
+
+bit:   expr '.' expr {
+               if ($3 < 0 || $3 > 7) {
+                       /* only 8 bits in a byte */
+                       error("Only eight bits in a byte");
+               }
+               $$ = 100000;    /* should really check $1 is valid */
+               if ($1 >= 0x20 && $1 <= 0x3F) {
+                       $$ = $1 * 8 + $3;
+               }
+               if ($1 >= 0x400 && $1 <= 0x43F) {
+                       $$ = ($1 - 0x400) * 8 + $3 + 0x200;
+               }
+       }
+       | REG '.' expr {
+               $$ = 100000;
+               if (find_size_reg($1) == SIZE8) {
+                       if ($3 < 0 || $3 > 7)
+                               error("byte reg has only 8 bits");
+                       $$ = reg($1) * 8 + $3;
+               }
+               if (find_size_reg($1) == SIZE16) {
+                       if ($3 < 0 || $3 > 15)
+                               error("word reg has only 16 bits");
+                       $$ = reg($1) * 16 + $3;
+               }
+       }
+       | BIT {$$ = $1;}
+
+jmpaddr:       WORD {
+                       $$ = $1;
+                       if (p1) build_target_list(lex_sym_name);
+               }
+             | NUMBER {
+                       if ($1 & 1) error("Jump target must be aligned");
+                       $$ = $1;
+               }
+
+
+expr:  value   {$$ = $1;}
+       | expr '+' expr {$$ = $1 + $3;}
+       | expr '-' expr {$$ = $1 - $3;}
+       | expr '*' expr {$$ = $1 * $3;}
+       | expr '/' expr {$$ = $1 / $3;}
+       | expr '&' expr {$$ = $1 & $3;}
+       | expr '|' expr {$$ = $1 | $3;}
+       | expr '^' expr {$$ = $1 ^ $3;}
+       | expr RSHIFT expr {$$ = $1 >> $3;}
+       | expr LSHIFT expr {$$ = $1 << $3;}
+       | '-' expr %prec UNARY {$$ = $2 * -1;}
+       | '+' expr %prec UNARY {$$ = $2;}
+       | '(' expr ')' {$$ = $2;}
+       | LOW expr %prec UNARY {$$ = $2 & 255;}
+       | HIGH expr %prec UNARY {$$ = ($2 >> 8) & 255;}
+
+
+value:   NUMBER {$$ = $1;}
+       | CHAR {$$ = $1;}
+       | WORD {
+         $$ = $1; 
+         if (expr_var[0][0]=='\0') {
+           strcpy(expr_var[0], yytext);
+         } else {
+           strcpy(expr_var[1], yytext);
+         }
+       }
+
+
+rlist: REG {
+               rlist_bitmask = 1<<(reg($1) % 8);
+               rlist_reg_bank = (reg($1) / 8) ? 1 : 0;
+               rlist_size = find_size_reg($1);
+       }
+       | REG ',' rlist {
+               rlist_bitmask |= 1<<(reg($1) % 8);
+               if (rlist_reg_bank != ((reg($1) / 8) ? 1 : 0))
+                       error("register list may not mix 0-7/8-15 regs");
+               if (rlist_size != find_size_reg($1))
+                       error("register list may not mix 8/16 bit registers");
+       }
+
+
+
+
+
+instruction:
+
+  arith_inst REG ',' REG {
+       $$ = 2;
+       size = find_size2(inst_size, $2, $4);
+       op[0] = arith_opcode * 16 + size * 8 + 1;
+       op[1] = reg($2) * 16 + reg($4);
+  }
+| arith_inst REG ',' '[' REG ']' {
+       $$ = 2;
+       size = find_size1(inst_size, $2);
+       op[0] = arith_opcode * 16 + size * 8 + 2;
+       op[1] = reg($2) * 16 + reg_indirect($5);
+  }
+| arith_inst '[' REG ']' ',' REG {
+       $$ = 2;
+       size = find_size1(inst_size, $6);
+       op[0] = arith_opcode * 16 + size * 8 + 2;
+       op[1] = reg($6) * 16 + 8 + reg_indirect($3);
+  }
+| arith_inst REG ',' '[' REG '+' expr ']' {
+       size = find_size1(inst_size, $2);
+       if ($7 >= -128 && $7 <= 127) {
+               $$ = 3;
+               op[0] = arith_opcode * 16 + size * 8 + 4;
+               op[1] = reg($2) * 16 + reg_indirect($5);
+               op[2] = ($7 >= 0) ? $7 : 256 + $7;
+               RELOC_ABS_FF(2,0);
+       } else {
+               $$ = 4;
+               op[0] = arith_opcode * 16 + size * 8 + 5;
+               op[1] = reg($2) * 16 + reg_indirect($5);
+               op[2] = ($7 >= 0) ? msb($7) : msb(65536 + $7);
+               op[3] = ($7 >= 0) ? lsb($7) : lsb(65536 + $7);
+               RELOC_ABS_FFFF(2,0);
+       }
+  }
+| arith_inst '[' REG '+' expr ']' ',' REG {
+       size = find_size1(inst_size, $8);
+       if ($5 >= -128 && $5 <= 127) {
+               $$ = 3;
+               op[0] = arith_opcode * 16 + size * 8 + 4;
+               op[1] = reg($8) * 16 + 8 + reg_indirect($3);
+               op[2] = ($5 >= 0) ? $5 : 256 + $5;
+               RELOC_ABS_FF(2,0);
+       } else {
+               $$ = 4;
+               op[0] = arith_opcode * 16 + size * 8 + 5;
+               op[1] = reg($8) * 16 + 8 + reg_indirect($3);
+               op[2] = ($5 >= 0) ? msb($5) : msb(65536 + $5);
+               op[3] = ($5 >= 0) ? lsb($5) : lsb(65536 + $5);
+               RELOC_ABS_FFFF(2,0);
+       }
+  }
+| arith_inst REG ',' '[' REG '+' ']' {
+       $$ = 2;
+       size = find_size1(inst_size, $2);
+       op[0] = arith_opcode * 16 + size * 8 + 3;
+       op[1] = reg($2) * 16 + reg_indirect($5);
+  }
+| arith_inst '[' REG '+' ']' ',' REG {
+       $$ = 2;
+       size = find_size1(inst_size, $7);
+       op[0] = arith_opcode * 16 + size * 8 + 3;
+       op[1] = reg($7) * 16 + 8 + reg_indirect($3);
+  }
+| arith_inst WORD ',' REG {
+       $$ = 3;
+       size = find_size1(inst_size, $4);
+       op[0] = arith_opcode * 16 + size * 8 + 6;
+       op[1] = reg($4) * 16 + 8 + msb(direct_addr($2));
+       op[2] = lsb(direct_addr($2));
+       RELOC_ABS_07ff(1, 0);
+  }
+| arith_inst REG ',' WORD {
+       $$ = 3;
+       size = find_size1(inst_size, $2);
+       op[0] = arith_opcode * 16 + size * 8 + 6;
+       op[1] = reg($2) * 16 + msb(direct_addr($4));
+       op[2] = lsb(direct_addr($4));
+       RELOC_ABS_07ff(1, 0);
+  }
+| arith_inst REG ',' '#' expr {
+       size = find_size1(inst_size, $2);
+       if (size == SIZE8) {
+               $$ = 3;
+               op[0] = 0x91;
+               op[1] = reg($2) * 16 + arith_opcode;
+               op[2] = imm_data8($5);
+               RELOC_ABS_FF(2, 0);
+       } else {
+               $$ = 4;
+               op[0] = 0x99;
+               op[1] = reg($2) * 16 + arith_opcode;
+               op[2] = msb(imm_data16($5));
+               op[3] = lsb(imm_data16($5));
+               RELOC_ABS_FFFF (2, 0);
+       }
+  }
+| arith_inst '[' REG ']' ',' '#' expr {
+       size = find_size0(inst_size);
+       if (size == SIZE8) {
+               $$ = 3;
+               op[0] = 0x92;
+               op[1] = reg_indirect($3) * 16 + arith_opcode;
+               op[2] = imm_data8($7);
+               RELOC_ABS_FF(2, 0);
+       } else {
+               $$ = 4;
+               op[0] = 0x9A;
+               op[1] = reg_indirect($3) * 16 + arith_opcode;
+               op[2] = msb(imm_data16($7));
+               op[3] = lsb(imm_data16($7));
+               RELOC_ABS_FFFF (2, 0);
+       }
+  }
+| arith_inst '[' REG '+' ']' ',' '#' expr {
+       size = find_size0(inst_size);
+       if (size == SIZE8) {
+               $$ = 3;
+               op[0] = 0x93;
+               op[1] = reg_indirect($3) * 16 + arith_opcode;
+               op[2] = imm_data8($8);
+               RELOC_ABS_FF(2, 0);
+       } else {
+               $$ = 4;
+               op[0] = 0x9B;
+               op[1] = reg_indirect($3) * 16 + arith_opcode;
+               op[2] = msb(imm_data16($8));
+               op[3] = lsb(imm_data16($8));
+               RELOC_ABS_FFFF (2, 0);
+       }
+  }
+| arith_inst '[' REG '+' expr ']' ',' '#' expr {
+       size = find_size0(inst_size);
+       if ($5 >= -128 && $5 <= 127) {
+               if (size == SIZE8) {
+                       $$ = 4;
+                       op[0] = 0x94;
+                       op[1] = reg_indirect($3) * 16 + arith_opcode;
+                       op[2] = ($5 >= 0) ? $5 : 256 + $5;
+                       op[3] = imm_data8($9);
+                       RELOC_ABS_FF(2, 0);
+                       RELOC_ABS_FF(3, 1);
+               } else {
+                       $$ = 5;
+                       op[0] = 0x9C;
+                       op[1] = reg_indirect($3) * 16 + arith_opcode;
+                       op[2] = ($5 >= 0) ? $5 : 256 + $5;
+                       op[3] = msb(imm_data16($9));
+                       op[4] = lsb(imm_data16($9));
+                       RELOC_ABS_FF(2, 0);
+                       RELOC_ABS_FFFF(3, 1);
+               }
+       } else {
+               if (size == SIZE8) {
+                       $$ = 5;
+                       op[0] = 0x95;
+                       op[1] = reg_indirect($3) * 16 + arith_opcode;
+                       op[2] = ($5 >= 0) ? msb($5) : msb(65536 + $5);
+                       op[3] = ($5 >= 0) ? lsb($5) : lsb(65536 + $5);
+                       op[4] = imm_data8($9);
+                       RELOC_ABS_FFFF(2,0);
+                       RELOC_ABS_FF(4,1);
+               } else {
+                       $$ = 6;
+                       op[0] = 0x9D;
+                       op[1] = reg_indirect($3) * 16 + arith_opcode;
+                       op[2] = ($5 >= 0) ? msb($5) : msb(65536 + $5);
+                       op[3] = ($5 >= 0) ? lsb($5) : lsb(65536 + $5);
+                       op[4] = msb(imm_data16($9));
+                       op[5] = lsb(imm_data16($9));
+                       RELOC_ABS_FFFF(2, 0);
+                       RELOC_ABS_FFFF(4, 1);
+               }
+       }
+  }
+| arith_inst WORD ',' '#' expr {
+        size = find_size0(inst_size);
+       if (size == SIZE8) {
+               $$ = 4;
+               op[0] = 0x96;
+               op[1] = msb(direct_addr($2)) * 16 + arith_opcode;
+               op[2] = lsb(direct_addr($2));
+               op[3] = imm_data8($5);
+               RELOC_ABS_F0FF(1,0);
+               RELOC_ABS_FF(3,1);
+       } else {
+               $$ = 5;
+               op[0] = 0x9E;
+               op[1] = msb(direct_addr($2)) * 16 + arith_opcode;
+               op[2] = lsb(direct_addr($2));
+               op[3] = msb(imm_data16($5));
+               op[4] = lsb(imm_data16($5));
+               RELOC_ABS_F0FF(1,0);
+               RELOC_ABS_FFFF (3,1);
+       }
+  }
+
+/* the next 8 instructions are MOV, but because MOV was used in the */
+/* arith_inst group, it will cause a shift/reduce conflict if used */
+/* directly below... so we're forced to use arith_inst and then */
+/* add a bit of code to make sure it was MOV and not the other ones */
+
+| arith_inst '[' REG '+' ']' ',' '[' REG '+' ']' {
+       /* this addr mode is only valid for MOV */
+       if (arith_opcode != 8) error("Addr mode only valid for MOV (1)");
+       size = find_size0(inst_size);
+       $$ = 2;
+       op[0] = 0x90 + size * 8;
+       op[1] = reg_indirect($3) * 16 + reg_indirect($8);
+  }
+| arith_inst WORD ',' '[' REG ']' {
+       /* this addr mode is only valid for MOV */
+       if (arith_opcode != 8) error("Addr mode only valid for MOV (2)");
+       size = find_size0(inst_size);
+       $$ = 3;
+       op[0] = 0xA0 + size * 8;
+       op[1] = 128 + reg_indirect($5) * 16 + msb(direct_addr($2));
+       op[2] = lsb(direct_addr($2));
+       RELOC_ABS_07ff(1, 0);
+  }
+| arith_inst '[' REG ']' ',' WORD {
+       /* this addr mode is only valid for MOV */
+       if (arith_opcode != 8) error("Addr mode only valid for MOV (3)");
+       size = find_size0(inst_size);
+       $$ = 3;
+       op[0] = 0xA0 + size * 8;
+       op[1] = reg_indirect($3) * 16 + msb(direct_addr($6));
+       op[2] = lsb(direct_addr($6));
+       RELOC_ABS_07ff(1, 0);
+  }
+| arith_inst WORD ',' WORD {
+       /* this addr mode is only valid for MOV */
+       if (arith_opcode != 8) error("Addr mode only valid for MOV (4)");
+       size = find_size0(inst_size);
+       $$ = 4;
+       op[0] = 0x97 + size * 8;
+       op[1] = msb(direct_addr($2)) * 16 + msb(direct_addr($4));
+       op[2] = lsb(direct_addr($2));
+       op[3] = lsb(direct_addr($4));
+       RELOC_ABS_F0FF(1, 0);
+       RELOC_ABS_0F00FF(1, 1);
+  }
+| arith_inst REG ',' USP {
+       /* this addr mode is only valid for MOV */
+       if (arith_opcode != 8) error("Addr mode only valid for MOV (5)");
+       $$ = 2;
+       op[0] = 0x90;
+       op[1] = reg($2) * 16 + 15;
+  }
+| arith_inst USP ',' REG {
+       /* this addr mode is only valid for MOV */
+       if (arith_opcode != 8) error("Addr mode only valid for MOV (6)");
+       $$ = 2;
+       op[0] = 0x98;
+       op[1] = reg($4) * 16 + 15;
+  }
+| arith_inst C ',' bit {
+       /* this addr mode is only valid for MOV */
+       if (arith_opcode != 8) error("Addr mode only valid for MOV (7)");
+       $$ = 3;
+       op[0] = 0x08;
+       op[1] = 0x20 + msb(bit_addr($4));
+       op[2] = lsb(bit_addr($4));
+       RELOC_ABS_03FF(1, 0);
+  }
+| arith_inst bit ',' C {
+       /* this addr mode is only valid for MOV */
+       if (arith_opcode != 8) error("Addr mode only valid for MOV (8)");
+       $$ = 3;
+       op[0] = 0x08;
+       op[1] = 0x30 + msb(bit_addr($2));
+       op[2] = lsb(bit_addr($2));
+       RELOC_ABS_03FF(1, 0);
+  }
+
+| MOVC REG ',' '[' REG '+' ']' {
+       size = find_size1(inst_size, $2);
+       $$ = 2;
+       op[0] = 0x80 + size * 8;
+       op[1] = reg($2) * 16 + reg_indirect($5);
+  }
+| MOVC A ',' '[' A '+' DPTR ']' {
+       $$ = 2;
+       op[0] = 0x90;
+       op[1] = 0x4E;
+  }
+| MOVC A ',' '[' A '+' PC ']' {
+       $$ = 2;
+       op[0] = 0x90;
+       op[1] = 0x4C;
+  }
+| MOVX REG ',' '[' REG ']' {
+       $$ = 2;
+       size = find_size1(inst_size, $2);
+       op[0] = 0xA7 + size * 8;
+       op[1] = reg($2) * 16 + reg_indirect($5);
+  }
+| MOVX '[' REG ']' ',' REG {
+       $$ = 2;
+       size = find_size1(inst_size, $6);
+       op[0] = 0xA7 + size * 8;
+       op[1] = reg($6) * 16 + 8 + reg_indirect($3);
+  }
+| XCH REG ',' REG {
+       $$ = 2;
+       size = find_size2(inst_size, $2, $4);
+       op[0] = 0x60 + size * 8;
+       op[1] = reg($2) * 16 + reg($4);
+  }
+| XCH REG ',' '[' REG ']' {
+       $$ = 2;
+       size = find_size1(inst_size, $2);
+       op[0] = 0x50 + size * 8;
+       op[1] = reg($2) * 16 + reg_indirect($5);
+  }
+| XCH REG ',' WORD {
+       $$ = 3;
+       size = find_size1(inst_size, $2);
+       op[0] = 0xA0 + size * 8;
+       op[1] = reg($2) * 16 + msb(direct_addr($4));
+        op[2] = lsb(direct_addr($4));
+       RELOC_ABS_07ff(1, 0);
+  }
+| short_data_inst REG ',' '#' expr {
+       $$ = 2;
+       size = find_size1(inst_size, $2);
+       op[0] = short_opcode + size * 8 + 1;
+       op[1] = reg($2) * 16 + imm_data4_signed($5);
+       RELOC_ABS_0F(1, 0);
+  }
+| short_data_inst '[' REG ']' ',' '#' expr {
+       $$ = 2;
+       size = find_size0(inst_size);
+       op[0] = short_opcode + size * 8 + 2;
+       op[1] = reg_indirect($3) * 16 + imm_data4_signed($7);
+       RELOC_ABS_0F(1, 0);
+  }
+| short_data_inst '[' REG '+' ']' ',' '#' expr {
+       $$ = 2;
+       size = find_size0(inst_size);
+       op[0] = short_opcode + size * 8 + 3;
+       op[1] = reg_indirect($3) * 16 + imm_data4_signed($8);
+       RELOC_ABS_0F(1, 0);
+  }
+| short_data_inst '[' REG '+' expr ']' ',' '#' expr {
+       size = find_size0(inst_size);
+       if ($5 >= -128 && $5 <= 127) {
+               $$ = 3;
+               op[0] = short_opcode + size * 8 + 4;
+               op[1] = reg_indirect($3) * 16 + imm_data4_signed($9);
+               op[2] = op[2] = ($5 >= 0) ? $5 : 256 + $5;
+               RELOC_ABS_0F(1, 1);
+               RELOC_ABS_FF(2, 0);
+       } else {
+               $$ = 4;
+               op[0] = short_opcode + size * 8 + 5;
+               op[1] = reg_indirect($3) * 16 + imm_data4_signed($9);
+               op[2] = ($5 >= 0) ? msb($5) : msb(65536 + $5);
+               op[3] = ($5 >= 0) ? lsb($5) : lsb(65536 + $5);
+               RELOC_ABS_0F(1, 1);
+               RELOC_ABS_FFFF(2, 0);
+       }
+  }
+| short_data_inst expr ',' '#' expr {
+       $$ = 3;
+       size = find_size0(inst_size);
+       op[0] = short_opcode + size * 8 + 6;
+       op[1] = msb(direct_addr($2)) * 16 + imm_data4_signed($5);
+       op[2] = lsb(direct_addr($2));
+       RELOC_ABS_0F(1, 0);
+  }
+| ANL C ',' bit {
+       $$ = 3;
+       op[0] = 0x08;
+       op[1] = 0x40 + msb(bit_addr($4));
+       op[2] = lsb(bit_addr($4));
+       RELOC_ABS_03FF(1, 0);
+  }
+| ANL C ',' '/' bit {
+       $$ = 3;
+       op[0] = 0x08;
+       op[1] = 0x50 + msb(bit_addr($5));
+       op[2] = lsb(bit_addr($5));
+       RELOC_ABS_03FF(1, 0);
+  }
+
+| ORL C ',' bit {
+       $$ = 3;
+       op[0] = 0x08;
+       op[1] = 0x60 + msb(bit_addr($4));
+       op[2] = lsb(bit_addr($4));
+       RELOC_ABS_03FF(1, 0);
+  }
+| ORL C ',' '/' bit {
+       $$ = 3;
+       op[0] = 0x08;
+       op[1] = 0x70 + msb(bit_addr($5));
+       op[2] = lsb(bit_addr($5));
+       RELOC_ABS_03FF(1, 0);
+  }
+| CLR bit {
+       $$ = 3;
+       op[0] = 0x08;
+       op[1] = msb(bit_addr($2));
+       op[2] = lsb(bit_addr($2));
+       RELOC_ABS_03FF(1, 0);
+  }
+| SETB bit {
+       $$ = 3;
+       op[0] = 0x08;
+       op[1] = 0x10 + msb(bit_addr($2));
+       op[2] = lsb(bit_addr($2));
+       RELOC_ABS_03FF(1, 0);
+  }
+| logical_shift_inst REG ',' REG {
+       size = find_size1(inst_size, $2);
+       if (find_size_reg($4) != SIZE8)
+               error("Second register in logical shift must be byte size");
+       $$ = 2;
+       op[0] = shift_reg_opcode;
+       switch (size) {
+               case SIZE8:  op[0] += 0; break;
+               case SIZE16: op[0] += 8; break;
+               case SIZE32: op[0] += 12; break;
+       }
+       op[1] = reg($2) * 16 + reg($4);
+  }
+| logical_shift_inst REG ',' '#' NUMBER {
+        size = find_size1(inst_size, $2);
+        $$ = 2;
+       if (shift_imm_opcode == -1)
+               error("NORM may not use a constant");
+        op[0] = shift_imm_opcode;
+        switch (size) {
+                case SIZE8:  op[0] += 0; break;
+                case SIZE16: op[0] += 8; break;
+                case SIZE32: op[0] += 12; break;
+        }
+       switch (size) {
+               case SIZE8:
+               case SIZE16:
+                       op[1] = reg($2) * 16 + imm_data4_unsigned($5);
+                       break;
+               case SIZE32:
+                       op[1] = (reg($2) / 2) * 32 + imm_data5_unsigned($5);
+                       break;
+       }
+  }
+| no_opperand_inst {
+       $$ = num_op;
+       op[0] = opcode0;
+       op[1] = opcode1;
+  }
+
+| TRAP '#' NUMBER {
+       $$ = 2;
+       op[0] = 0xD6;
+       op[1] = 0x30 + imm_data4_unsigned($3);
+  }
+| CPL REG {
+       $$ = 2;
+       size = find_size1(inst_size, $2);
+       op[0] = 0x90 + size * 8;
+       op[1] = reg($2) * 16 + 10;
+  }
+| DA REG {
+       $$ = 2;
+       op[0] = 0x90;
+       op[1] = reg($2) * 16 + 8;
+  }
+| NEG REG {
+       $$ = 2;
+       size = find_size1(inst_size, $2);
+       op[0] = 0x90 + size * 8;
+       op[1] = reg($2) * 16 + 11;
+  }
+| SEXT REG {
+       $$ = 2;
+       size = find_size1(inst_size, $2);
+       op[0] = 0x90 + size * 8;
+       op[1] = reg($2) * 16 + 9;
+  }
+
+| rotate_inst REG ',' '#' NUMBER {
+       $$ = 2;
+       size = find_size1(inst_size, $2);
+       op[0] = rotate_opcode + size * 8;
+       op[1] = reg($2) * 16 + imm_data4_unsigned($5);
+  }
+
+
+| LEA REG ',' REG '+' expr {
+       if ($6 >= -128 && $6 <= 127) {
+               $$ = 3;
+               op[0] = 0x40;
+               op[1] = reg($2) * 16 + reg_indirect($4);
+               op[2] = ($6 >= 0) ? $6 : 256 + $6;
+               RELOC_ABS_FF(2, 0);
+       } else {
+               op[0] = 0x48;
+               op[1] = reg($2) * 16 + reg_indirect($4);
+               op[2] = ($6 >= 0) ? msb($6) : msb(65536 + $6);
+               op[3] = ($6 >= 0) ? lsb($6) : lsb(65536 + $6);
+               RELOC_ABS_FFFF(2, 0);
+       }
+  }
+| stack_inst WORD {
+       $$ = 3;
+       size = find_size0(inst_size);
+       op[0] = msb(stack_addr_opcode) + size * 8;
+       op[1] = lsb(stack_addr_opcode) + msb(direct_addr($2));
+       op[2] = lsb(direct_addr($2));
+       RELOC_ABS_07ff(1, 0);
+  }
+| stack_inst rlist {
+       $$ = 2;
+       if (inst_size != UNKNOWN && find_size0(inst_size) != rlist_size)
+               error("inst specifies different size than registers used");
+       op[0] = stack_reg_opcode + rlist_reg_bank * 64 + rlist_size * 8;
+       op[1] = rlist_bitmask;
+  }
+
+
+| MUL REG ',' REG {
+       $$ = 2;
+       size = find_size2(inst_size, $2, $4);
+       op[0] = 0xE6;
+       op[1] = reg($2) * 16 + reg($4);
+  }
+| MULU REG ',' REG {
+       $$ = 2;
+       size = find_size2(inst_size, $2, $4);
+       if (size == SIZE8) {
+               op[0] = 0xE0;
+               op[1] = reg($2) * 16 + reg($4);
+       } else {
+               op[0] = 0xE4;
+               op[1] = reg($2) * 16 + reg($4);
+       }
+  }
+| MUL REG ',' '#' expr {
+       $$ = 2;
+       size = find_size1(inst_size, $2);
+       op[0] = 0xE9;
+       op[1] = reg($2) + 8;
+       op[2] = msb(imm_data16($5));
+       op[3] = lsb(imm_data16($5));
+       RELOC_ABS_FFFF(2, 0);
+  }
+| MULU REG ',' '#' expr {
+       size = find_size2(inst_size, $2, $4);
+       if (size == SIZE8) {
+               $$ = 3;
+               op[0] = 0xE8;
+               op[1] = reg($2) * 16;
+               op[2] = imm_data8($5);
+               RELOC_ABS_FF(2, 0);
+       } else {
+               $$ = 4;
+               op[0] = 0xE9;
+               op[1] = reg($2) * 16;
+               op[2] = msb(imm_data16($5));
+               op[3] = lsb(imm_data16($5));
+               RELOC_ABS_FFFF(2, 0);
+       }
+  }
+| DIV REG ',' REG {
+       $$ = 2;
+       size = find_size2(inst_size, $2, $4);
+       switch (size) {
+       case SIZE8:
+               error("Singed DIV can't be 8 bit size"); break;
+       case SIZE16:
+               op[0] = 0xE7;
+               op[1] = reg($2) * 16 + reg($4);
+               break;
+       case SIZE32:
+               op[0] = 0xEF;
+               op[1] = (reg($2) / 2) * 32 + reg($4);
+               break;
+       }
+  }
+| DIVU REG ',' REG {
+       $$ = 2;
+       size = find_size2(inst_size, $2, $4);
+       switch (size) {
+       case SIZE8:
+               op[0] = 0xE1;
+               op[1] = reg($2) * 16 + reg($4);
+               break;
+       case SIZE16:
+               op[0] = 0xE5;
+               op[1] = reg($2) * 16 + reg($4);
+               break;
+       case SIZE32:
+               op[0] = 0xED;
+               op[1] = (reg($2) / 2) * 32 + reg($4);
+               break;
+       }
+  }
+| DIV REG ',' '#' expr { 
+       size = find_size1(inst_size, $2);
+       switch (size) {
+       case SIZE8:
+               error("Singed DIV can't be 8 bit size"); break;
+       case SIZE16:
+               $$ = 3;
+               op[0] = 0xE8;
+               op[1] = reg($2) * 16 + 11;
+               op[2] = imm_data8($5);
+               RELOC_ABS_FF(2, 0);
+               break;
+       case SIZE32:
+               $$ = 4;
+               op[0] = 0xE9;
+               op[1] = (reg($2) / 2) * 32 + 9;
+               op[2] = msb(imm_data16($5));
+               op[3] = lsb(imm_data16($5));
+               RELOC_ABS_FFFF(2, 0);
+               break;
+       }
+  }
+| DIVU REG ',' '#' expr { 
+       size = find_size1(inst_size, $2);
+       switch (size) {
+       case SIZE8:
+               $$ = 3;
+               op[0] = 0xE8;
+               op[1] = reg($2) * 16 + 1;
+               op[2] = imm_data8($5);
+               RELOC_ABS_FF(2, 0);
+               break;
+       case SIZE16:
+               $$ = 3;
+               op[0] = 0xE8;
+               op[1] = reg($2) * 16 + 3;
+               op[2] = imm_data8($5);
+               RELOC_ABS_FF(2, 0);
+               break;
+       case SIZE32:
+               $$ = 4;
+               op[0] = 0xE9;
+               op[1] = (reg($2) / 2) * 32 + 1;
+               op[2] = msb(imm_data16($5));
+               op[3] = lsb(imm_data16($5));
+               RELOC_ABS_FFFF(2, 0);
+               break;
+       }
+  }
+| CALL '[' REG ']' {
+       $$ = 2;
+       op[0] = 0xC6;
+       op[1] = reg($3);
+  }
+| FCALL jmpaddr {
+       $$ = 4;
+       op[0] = 0xC4;
+       op[1] = ($2 >> 8) & 255;
+       op[2] = $2 & 255;
+       op[3] = ($2 >> 16) & 255;
+  }
+| FJMP jmpaddr {
+       $$ = 4;
+       op[0] = 0xD4;
+       op[1] = ($2 >> 8) & 255;
+       op[2] = $2 & 255;
+       op[3] = ($2 >> 16) & 255;
+  }
+| JMP '[' REG ']' {
+       $$ = 2;
+       op[0] = 0xD6;
+       op[1] = 0x70 + reg_indirect($3);
+  }
+| JMP '[' A '+' DPTR ']' {
+       $$ = 2;
+       op[0] = 0xD6;
+       op[1] = 0x46;
+  }
+| JMP '[' '[' REG '+' ']' ']' {
+       $$ = 2;
+       op[0] = 0xD6;
+       op[1] = 0x60 + reg_indirect($4);
+  }
+
+| JMP jmpaddr {
+       $$ = 3;
+       op[0] = 0xD5;
+       op[1] = msb(rel16(MEM_POS + $$, $2));
+       op[2] = lsb(rel16(MEM_POS + $$, $2));
+       RELOC_FFFF(MEM_POS+$$,1,0);
+  }
+
+| CALL jmpaddr {
+        $$ = 3;
+        op[0] = 0xC5;
+        op[1] = msb(rel16(MEM_POS + $$, $2));
+        op[2] = lsb(rel16(MEM_POS + $$, $2));
+       RELOC_FFFF(MEM_POS+$$,1,0);
+  }
+| branch_inst jmpaddr {
+       $$ = 2;
+       op[0] = branch_opcode;
+       op[1] = rel8(MEM_POS + $$, $2);
+       RELOC_FF(MEM_POS + $$, 1,0);
+  }
+| CJNE REG ',' expr ',' jmpaddr {
+        $$ = 4;
+       size = find_size1(inst_size, $2);
+       op[0] = 0xE2 + size * 8;
+       op[1] = reg($2) * 16 + msb(direct_addr($4));
+       op[2] = lsb(direct_addr($4));
+       op[3] = rel8(MEM_POS + $$, $6);
+       RELOC_ABS_07ff(1, 0);
+       RELOC_FF(MEM_POS + $$, 3,1);
+  }
+| CJNE REG ',' '#' expr ',' jmpaddr {
+       size  = find_size1(inst_size, $2);
+       if (size == SIZE8) {
+               $$ = 4;
+               op[0] = 0xE3;
+               op[1] = reg($2) * 16;
+               op[2] = rel8(MEM_POS + $$, $7);
+               op[3] = imm_data8($5);
+               RELOC_ABS_FF(3, 0);
+       } else {
+               $$ = 5;
+               op[0] = 0xEB;
+               op[1] = reg($2) * 16;
+               op[2] = rel8(MEM_POS + $$, $7);
+               op[3] = msb(imm_data16($5));
+               op[4] = lsb(imm_data16($5));
+               RELOC_ABS_FFFF(3, 0);
+       }
+  }
+| CJNE '[' REG ']' ',' '#' expr ',' jmpaddr {
+       size  = find_size0(inst_size);
+       if (size == SIZE8) {
+               $$ = 4;
+               op[0] = 0xE3;
+               op[1] = reg_indirect($3) * 16 + 8;
+               op[2] = rel8(MEM_POS + $$, $9);
+               op[3] = imm_data8($7);
+               RELOC_ABS_FF(3, 0);
+       } else {
+               $$ = 5;
+               op[0] = 0xEB;
+               op[1] = reg_indirect($3) * 16 + 8;
+               op[2] = rel8(MEM_POS + $$, $9);
+               op[3] = msb(imm_data16($7));
+               op[4] = lsb(imm_data16($7));
+               RELOC_ABS_FFFF(3, 0);
+       }
+  }
+| DJNZ REG ',' jmpaddr {
+       $$ = 3;
+       size  = find_size1(inst_size, $2);
+       op[0] = 0x87 + size * 8;
+       op[1] = reg($2) * 16 + 8;
+       op[2] = rel8(MEM_POS + $$, $4);
+       RELOC_FF(MEM_POS+$$, 2, 0);
+  }
+
+
+| DJNZ WORD ',' jmpaddr {
+       $$ = 4;
+       size  = find_size0(inst_size);
+       op[0] = 0xE2 + size * 8;
+       op[1] = msb(direct_addr($2)) + 8;
+       op[2] = lsb(direct_addr($2));
+       op[3] = rel8(MEM_POS + $$, $4);
+       RELOC_ABS_07ff(1, 0);
+       RELOC_FF(MEM_POS + $$, 3, 1)
+  }
+
+| JB bit ',' jmpaddr {
+       $$ = 4;
+       op[0] = 0x97;
+       op[1] = 0x80 + msb(bit_addr($2));
+       op[2] = lsb(bit_addr($2));
+       op[3] = rel8(MEM_POS + $$, $4);
+       RELOC_ABS_03FF(1, 0);
+       RELOC_FF(MEM_POS + $$, 3, 1);
+  }
+
+| JBC bit ',' jmpaddr {
+       $$ = 4;
+       op[0] = 0x97;
+       op[1] = 0xC0 + msb(bit_addr($2));
+       op[2] = lsb(bit_addr($2));
+       op[3] = rel8(MEM_POS + $$, $4);
+       RELOC_ABS_03FF(1, 0);
+       RELOC_FF(MEM_POS + $$, 3, 1);
+  }
+
+| JNB bit ',' jmpaddr {
+       $$ = 4;
+       op[0] = 0x97;
+       op[1] = 0xA0 + msb(bit_addr($2));
+       op[2] = lsb(bit_addr($2));
+       op[3] = rel8(MEM_POS + $$, $4);
+       RELOC_ABS_03FF(1, 0);
+       RELOC_FF(MEM_POS + $$, 3, 1);
+  }
+
+
+arith_inst:
+         ADD   {arith_opcode = 0;}
+       | ADDC  {arith_opcode = 1;}
+       | AND   {arith_opcode = 5;}
+       | CMP   {arith_opcode = 4;}
+       | MOV   {arith_opcode = 8;}
+       | OR    {arith_opcode = 6;}
+       | SUB   {arith_opcode = 2;}
+       | SUBB  {arith_opcode = 3;}
+       | XOR   {arith_opcode = 7;}
+
+short_data_inst:
+         ADDS {short_opcode = 0xA0;}
+       | MOVS {short_opcode = 0xB0;}
+
+logical_shift_inst:
+         ASL  {shift_reg_opcode = 0xC1; shift_imm_opcode = 0xD1;}
+       | ASR  {shift_reg_opcode = 0xC2; shift_imm_opcode = 0xD2;}
+       | LSR  {shift_reg_opcode = 0xC0; shift_imm_opcode = 0xD0;}
+       | NORM {shift_reg_opcode = 0xC3; shift_imm_opcode = -1;}
+
+rotate_inst:
+         RL    {rotate_opcode = 0xD3;}
+       | RLC   {rotate_opcode = 0xD7;}
+       | RR    {rotate_opcode = 0xD0;}
+       | RRC   {rotate_opcode = 0xD7;}
+
+stack_inst:
+         POP   {stack_addr_opcode = 0x8710; stack_reg_opcode = 0x27;}
+       | POPU  {stack_addr_opcode = 0x8700; stack_reg_opcode = 0x37;}
+       | PUSH  {stack_addr_opcode = 0x8730; stack_reg_opcode = 0x07;}
+       | PUSHU {stack_addr_opcode = 0x8720; stack_reg_opcode = 0x17;}
+
+no_opperand_inst:
+         BKPT  {num_op = 1; opcode0 = 255; opcode1 = 0;}
+       | NOP   {num_op = 1; opcode0 = 0; opcode1 = 0;}
+       | RESET {num_op = 2; opcode0 = 0xD6; opcode1 = 0x10;}
+       | RET   {num_op = 2; opcode0 = 0xD6; opcode1 = 0x80;}
+       | RETI  {num_op = 2; opcode0 = 0xD6; opcode1 = 0x90;}
+
+branch_inst:
+         BCC   {branch_opcode = 0xF0;}
+       | BCS   {branch_opcode = 0xF1;}
+       | BEQ   {branch_opcode = 0xF3;}
+       | BG    {branch_opcode = 0xF8;}
+       | BGE   {branch_opcode = 0xFA;}
+       | BGT   {branch_opcode = 0xFC;}
+       | BL    {branch_opcode = 0xF9;}
+       | BLE   {branch_opcode = 0xFD;}
+       | BLT   {branch_opcode = 0xFB;}
+       | BMI   {branch_opcode = 0xF7;}
+       | BNE   {branch_opcode = 0xF2;}
+       | BNV   {branch_opcode = 0xF4;}
+       | BOV   {branch_opcode = 0xF5;}
+       | BPL   {branch_opcode = 0xF6;}
+       | BR    {branch_opcode = 0xFE;}
+       | JZ    {branch_opcode = 0xEC;}
+       | JNZ   {branch_opcode = 0xEE;}
+
+
+
+%%
+
+
+int reg(int reg_spec)
+{
+       return reg_spec & 15;
+}
+
+int reg_indirect(int reg_spec)
+{
+       if (reg_spec & BYTE_REG)
+               error("Indirect addressing may not use byte registers");
+       if ((reg_spec & 15) > 7)
+               error("Only R0 through R7 may be used for indirect addr");
+       return reg_spec & 7;
+}
+
+int rel16(int pos, int dest)
+{
+       int rel;
+
+       if (!p3) return 0;      /* don't bother unless writing code */
+       if (dest & (BRANCH_SPACING - 1))
+               error("Attempt to jump to unaligned location");
+       pos &= ~(BRANCH_SPACING - 1);
+       rel = (dest - pos) / BRANCH_SPACING;
+       if (rel < -32768 || rel > 32767)
+               error("Attempt to jump out of 16 bit relative range");
+       if (rel < 0) rel += 65536;
+       return rel;
+}
+
+int rel8(int pos, int dest)
+{
+       int rel;
+
+       if (!p3) return 0;      /* don't bother unless writing code */
+       if (dest & (BRANCH_SPACING - 1))
+               error("Attempt to jump to unaligned location");
+       pos &= ~(BRANCH_SPACING - 1);
+       rel = (dest - pos) / BRANCH_SPACING;
+       if (rel < -128 || rel > 127)
+               error("Attempt to jump out of 16 bit relative range");
+       if (rel < 0) rel += 256;
+       return rel;
+}
+
+int msb(int value)
+{
+       return (value >> 8) & 255;
+}
+
+int lsb(int value)
+{
+       return value & 255;
+}
+
+int direct_addr(int value)
+{
+       char buf[250];
+
+       if (value < 0 || value > 2047) {
+               sprintf(buf, "illegal value (%d) for direct address", value);
+               error(buf);
+       }
+       return value;
+}
+
+int imm_data4_signed(int value)
+{
+       if (value < -8 || value > 7)
+               error("illegal 4 bit (signed) value");
+       if (value >= 0) return value;
+       else return (16 + value);
+}
+
+int imm_data4_unsigned(int value)
+{
+       if (value < 0 || value > 15)
+               error("illegal 4 bit (unsigned) value");
+       return value;
+}
+
+int imm_data5_unsigned(int value)
+{
+       if (value < 0 || value > 31)
+               error("illegal 5 bit (unsigned) value");
+       return value;
+}
+
+int imm_data8(int value)
+{
+       if (value < -128 || value > 255)
+               error("illegal 8 bit value");
+       if (value >= 0) return value;
+       else return (256 + value);
+}
+
+int imm_data16(int value)
+{
+       if (value < -32728 || value > 65535)
+               error("illegal 16 bit value");
+       if (value >= 0) return value;
+       else return (65536 + value);
+}
+
+int bit_addr(int value)
+{
+       if (value < 0 || value > 1023) {
+               fprintf(stderr, "bad bit addr of 0x%04X (%d dec)\n",
+                       value, value);
+               error("illegal bit address");
+       }
+       return value;
+}
+
+
+int find_size_reg(int op1spec)
+{
+       int op1size=UNKNOWN;
+
+       if (op1spec & BYTE_REG) op1size = SIZE8;
+       if (op1spec & WORD_REG) op1size = SIZE16;
+       if (op1size == UNKNOWN)
+               error("Register without implied size");
+       return op1size;
+}
+
+int find_size0(int isize)
+{
+       if (isize == UNKNOWN)
+               error("Can't determine data size from instruction");
+       return isize;
+}
+
+int find_size1(int isize, int op1spec)
+{
+       int op1size=UNKNOWN;
+
+       if (op1spec & BYTE_REG) op1size = SIZE8;
+       if (op1spec & WORD_REG) op1size = SIZE16;
+       if (op1size == UNKNOWN)
+               error("Register without implied size");
+
+       if (isize == SIZE32 && op1size == SIZE16) return SIZE32;
+       if (isize == UNKNOWN) return op1size;
+       else {
+               if (isize != op1size)
+                       error("data size of register and inst don't agree");
+               return isize;
+       }
+}
+
+int find_size2(int isize, int op1spec, int op2spec)
+{
+       int op1size=UNKNOWN, op2size=UNKNOWN;
+
+       if (op1spec & BYTE_REG) op1size = SIZE8;
+       if (op1spec & WORD_REG) op1size = SIZE16;
+       if (op1size == UNKNOWN)
+               error("Register without implied size");
+       if (op2spec & BYTE_REG) op2size = SIZE8;
+       if (op2spec & WORD_REG) op2size = SIZE16;
+       if (op1size == UNKNOWN)
+               error("Register without implied size");
+
+       if (op1size != op2size)
+               error("data sizes of two registers don't agree");
+       if (isize == UNKNOWN) return op1size;
+       else {
+               if (isize != op1size)
+                       error("data size of registers and inst don't agree");
+               return isize;
+       }
+}
+
+int yyerror(char *s)
+{
+       if (yytext[0] >= 32) {
+               fprintf(stderr, "%s near '%s', line %d\n",
+                       s, yytext, lineno);
+       } else {
+               fprintf(stderr, "%s, line %d\n", s, lineno - 1);
+       }
+       return 0;
+}
+
+void error(char *s)
+{
+       yyerror(s);
+       exit(1);
+}
+
+int yywrap()
+{
+       return 1;
+}
index bbe19657fd7c3441c47d3c4f401548bf9cfb00cb..bd3e2b07324593b39ccc9ef814abda8a53945918 100755 (executable)
@@ -1,15 +1,22 @@
 #include <xa.h>
 
 bit b1, b2=1;
+code c1=0;
 data d1, d2=2;
 xdata x1, x2=3;
 
+extern bit be;
+extern code ce;
+extern data de;
+extern xdata xe;
+
 #define        BAUD_RATE 9600
 #define        OSC 20000000L   /* Xtal frequency */
 
 #define        DIVIDER (OSC/(64L*BAUD_RATE))
 
 void external_startup(void) {
+  xe=0;
   _asm
     mov.b      _WDCON,#0       ;shut down the watchdog
     mov.b      _WFEED1,#0a5h
@@ -55,6 +62,7 @@ void putchar(char c) {
 }
 #endif
 
+#if 0
 char getchar(void) {
   char c;
   
@@ -64,6 +72,9 @@ char getchar(void) {
   RI0=0;
   return c;
 }
+#else
+char getchar();
+#endif
 
 void puts(char *s) {
   while (*s) {
@@ -76,6 +87,7 @@ int kbhit(void) {
 }
 
 void main(void) {
+  xe=getchar();
   putchar('1');
   putchar('2');
   putchar('3');
index 65f7b3f8fe73cd624513004a21afff1b56f861f4..14190ca02e30dcf424a51dafe316d173493a20ca 100755 (executable)
@@ -332,7 +332,7 @@ static asmop *aopForSym(symbol *sym,
        }
     } else {
       aop->type=AOP_FAR;
-      emitcode ("mov", "r0,#%s ; aopForSym:far", sym->rname);
+      emitcode ("mov.w", "r0,#%s ; aopForSym:far", sym->rname);
       sprintf (aop->name[0], "[r0]");
       if (size>2) {
        sprintf (aop->name[1], "[r0+2]");
@@ -1221,7 +1221,11 @@ static void genPointerGet (iCode * ic, iCode *pi) {
   bool codePointer=IS_CODEPTR(operandType(left));
   int size;
 
-  printIc ("genPointerGet", ic, 1,1,0);
+  if (pi) {
+    printIc ("genPointerGet pi", ic, 1,1,0);
+  } else {
+    printIc ("genPointerGet", ic, 1,1,0);
+  }
 
   if (!IS_PTR(operandType(left))) {
     bailOut ("genPointerGet: pointer required");
@@ -1400,7 +1404,7 @@ static void genIfx (iCode * ic, iCode * popIc) {
   int size;
   char *instr;
   bool trueOrFalse;
-  symbol *jlbl, *tlbl;
+  symbol *jlbl, *tlbl=newiTempLabel(NULL);
   operand *cond=IC_COND(ic);
 
   emitcode (";", "genIfx(%d) cond=%s trueLabel:%s falseLabel:%s", 
@@ -1421,14 +1425,15 @@ static void genIfx (iCode * ic, iCode * popIc) {
   switch (AOP_TYPE(cond) )
     {
     case AOP_BIT:
-      emitcode (trueOrFalse ? "jb" : "jnb", "%s,%05d$", 
-               AOP_NAME(cond)[0], jlbl->key+100);
+      emitcode (trueOrFalse ? "jnb" : "jb", "%s,%05d$", 
+               AOP_NAME(cond)[0], tlbl->key+100);
+      emitcode ("jmp", "%05d$", jlbl->key+100);
+      emitcode ("", "%05d$:", tlbl->key+100);
       return;
     case AOP_REG:
     case AOP_DIR:
     case AOP_FAR:
     case AOP_STK:
-      tlbl=newiTempLabel(NULL);
       if (size>1) {
        instr="cmp.w";
       } else {
@@ -1632,6 +1637,7 @@ static void genCast (iCode * ic) {
       } else {
        /* we have to go by the storage class */
        if (!SPEC_OCLS(etype)) {
+         ptrType=0; // hush the compiler
          bailOut("genCast: unknown storage class");
        } else {
          ptrType = PTR_TYPE (SPEC_OCLS (etype));
@@ -1672,13 +1678,21 @@ static void genCast (iCode * ic) {
     case 0x11:
       emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
       return;
+    case 0x42:
+      emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
+      if (signedness) {
+       emitcode("sext", "%s", AOP_NAME(result)[1]);
+      } else {
+       emitcode("mov", "%s,#0", AOP_NAME(result)[1]);
+      }
+      return;
     case 0x41:
     case 0x21:
       emitcode("mov", "r1l,%s", AOP_NAME(right)[0]);
       if (signedness) {
        emitcode("sext", "r1h");
       } else {
-       emitcode("mov", "rlh,#0");
+       emitcode("mov", "r1h,#0");
       }
       emitcode("mov", "%s,r1", AOP_NAME(result)[0]);
       if (size==2)
@@ -1686,15 +1700,14 @@ static void genCast (iCode * ic) {
       // fall through: case 0x41
       emitcode("sext", AOP_NAME(result)[1]);
       return;
-    case 14:
-    case 12:
+    case 0x14:
+    case 0x12:
       emitcode("mov", "r1,%s", AOP_NAME(right)[0]);
       emitcode("mov", "%s,r1l", AOP_NAME(result)[0]);
       return;
-    case 24:
-      emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
-      return;
     }
+  fprintf(stderr, "genCast: unknown size: %d:%d\n",
+         AOP_SIZE(result), AOP_SIZE(right));
   bailOut("genCast: unknown size");
 }
 
index 6db62f3cebc4bc1f45d9fa124f0ec8ff1acc67f3..60cb2d10caa419f8c06ba099d991457f3a47db2d 100755 (executable)
@@ -139,8 +139,6 @@ _xa51_genAssemblerPreamble (FILE * of)
   symbol *mainExists=newSymbol("main", 0);
   mainExists->block=0;
 
-  fprintf (of, "_errno\tsfr\t0x00; to keep the fp-lib's happy for now\n\n");
-
   if ((mainExists=findSymWithLevel(SymbolTab, mainExists))) {
     fprintf (of, "\t.area CSEG\t(CODE)\n");
     fprintf (of, "__interrupt_vect:\n");
@@ -199,7 +197,7 @@ static const char *_linkCmd[] =
 /* $3 is replaced by assembler.debug_opts resp. port->assembler.plain_opts */
 static const char *_asmCmd[] =
 {
-  "xa_asm", "$l", "$3", "$1.xa", NULL
+  "xa_rasm", "$l", "$3", "$1.xa", NULL
 };
 
 /* Globals */
index 0d0ece9c7734d038c62c6aa7203a2ff6f55946b0..7a77a8747f8ca0ea1779633b0bfc1885480fb735 100644 (file)
@@ -95,6 +95,10 @@ test-ds390:
 test-ucz80:
        $(MAKE) inter-port-clean test-port PORT=ucz80
 
+# Helper rule for testing the xa51 port only(use ucSim simulator)
+test-xa51:
+       $(MAKE) inter-port-clean test-port PORT=xa51
+
 ### Helper rule for testing the host cc only
 test-host:
        $(MAKE) inter-port-clean test-port PORT=host
diff --git a/support/regression/ports/xa51/spec.mk b/support/regression/ports/xa51/spec.mk
new file mode 100755 (executable)
index 0000000..39b98d7
--- /dev/null
@@ -0,0 +1,38 @@
+# Port specification for the xa51 port running with uCsim
+
+# path to uCsim
+SXA_A = $(SDCC_DIR)/sim/ucsim/xa.src/sxa
+SXA_B = $(SDCC_DIR)/bin/sxa
+
+SXA = $(shell if [ -f $(SXA_A) ]; then echo $(SXA_A); else echo $(SXA_B); fi)
+
+SDCCFLAGS +=-mxa51 --lesspedantic -DREENTRANT=
+
+OBJEXT = .xa
+EXEEXT = .hex
+
+EXTRAS = fwk/lib/testfwk$(OBJEXT) $(PORTS_DIR)/$(PORT)/support$(OBJEXT)
+
+# Rule to link into .hex
+%$(EXEEXT): %$(OBJEXT) $(EXTRAS)
+       $(SDCC) $(SDCCFLAGS) $(EXTRAS) $<
+       mv fwk/lib/testfwk.hex $@
+       mv fwk/lib/testfwk.map $(@:.hex=.map)
+
+%$(OBJEXT): %.c
+       $(SDCC) $(SDCCFLAGS) -c $<
+
+# run simulator with 10 seconds timeout
+%.out: %$(EXEEXT) fwk/lib/timeout
+       mkdir -p `dirname $@`
+       -fwk/lib/timeout 10 $(SXA) -S in=/dev/null,out=$@ $< < $(PORTS_DIR)/xa51/uCsim.cmd >/dev/null || \
+          echo -e --- FAIL: \"timeout, simulation killed\" in $(<:.ihx=.c)"\n"--- Summary: 1/1/1: timeout >> $@
+       -grep -n FAIL $@ /dev/null || true
+
+fwk/lib/timeout: fwk/lib/timeout.c
+
+_clean:
+       rm -f fwk/lib/timeout fwk/lib/timeout.exe $(PORTS_DIR)/$(PORT)/*.rel $(PORTS_DIR)/$(PORT)/*.rst \
+             $(PORTS_DIR)/$(PORT)/*.lst $(PORTS_DIR)/$(PORT)/*.sym $(PORTS_DIR)/$(PORT)/*.xa temp.lnk
+
+
diff --git a/support/regression/ports/xa51/support.c b/support/regression/ports/xa51/support.c
new file mode 100755 (executable)
index 0000000..fa3f3cd
--- /dev/null
@@ -0,0 +1,41 @@
+/*-------------------------------------------------------------------------
+  support.c - startup for regression tests with uCsim
+  
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+   In other words, you are welcome to use, share and improve this program.
+   You are forbidden to forbid anyone else to use, share and improve
+   what you give them.   Help stamp out software-hoarding!
+-------------------------------------------------------------------------*/
+
+#include <tinibios.h>
+
+void
+_putchar (char c)
+{
+  _asm
+    mov.b r0l,[r7+2]
+    trap #0x0e
+  _endasm;
+}
+
+void
+_exitEmu (void)
+{
+  _asm
+    trap #0x0f
+  _endasm;
+}
+
diff --git a/support/regression/ports/xa51/uCsim.cmd b/support/regression/ports/xa51/uCsim.cmd
new file mode 100755 (executable)
index 0000000..4023f20
--- /dev/null
@@ -0,0 +1 @@
+go