OpenCores
URL https://opencores.org/ocsvn/eco32/eco32/trunk

Subversion Repositories eco32

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /eco32/tags/eco32-0.25/monitor/monitor
    from Rev 242 to Rev 248
    Reverse comparison

Rev 242 → Rev 248

/boards/s3e-500/start.s
0,0 → 1,496
;
; start.s -- ECO32 ROM monitor startup and support routines
;
 
.set BIO_BASE,0xF1000000 ; board I/O base address
.set BIO_WR,BIO_BASE+0
.set SPI_EN,0x80000000 ; SPI bus enable ctrl bit
.set BIO_RD,BIO_BASE+4
.set CIO_CTRL,0x08 ; this bit controls console I/O
 
.set CIO_KBD_DSP,0x00 ; set console to keyboard/display
.set CIO_SERIAL_0,0x03 ; set console to serial line 0
 
.set dmapaddr,0xC0000000 ; base of directly mapped addresses
.set stacktop,0xC0010000 ; monitor stack is at top of 64K
 
.set PSW,0 ; reg # of PSW
.set V_SHIFT,27 ; interrupt vector ctrl bit
.set V,1 << V_SHIFT
 
.set TLB_INDEX,1 ; reg # of TLB Index
.set TLB_ENTRY_HI,2 ; reg # of TLB EntryHi
.set TLB_ENTRY_LO,3 ; reg # of TLB EntryLo
.set TLB_ENTRIES,32 ; number of TLB entries
.set BAD_ADDRESS,4 ; reg # of bad address reg
.set BAD_ACCESS,5 ; reg # of bad access reg
 
.set USER_CONTEXT_SIZE,38*4 ; size of user context
 
;***************************************************************
 
.import _ecode
.import _edata
.import _ebss
 
.import kbdinit
.import kbdinchk
.import kbdin
 
.import dspinit
.import dspoutchk
.import dspout
 
.import ser0init
.import ser0inchk
.import ser0in
.import ser0outchk
.import ser0out
 
.import ser1init
.import ser1inchk
.import ser1in
.import ser1outchk
.import ser1out
 
.import dskinitctl
.import dskcapctl
.import dskioctl
 
.import dskinitser
.import dskcapser
.import dskioser
 
.import main
 
.export _bcode
.export _bdata
.export _bbss
 
.export setcon
.export cinchk
.export cin
.export coutchk
.export cout
.export dskcap
.export dskio
 
.export getTLB_HI
.export getTLB_LO
.export setTLB
 
.export saveState
.export monitorReturn
 
.import userContext
.export resume
 
;***************************************************************
 
.code
_bcode:
 
.data
_bdata:
 
.bss
_bbss:
 
;***************************************************************
 
.code
.align 4
 
startup:
j start
 
interrupt:
j debug
 
userMiss:
j debug
 
monitor:
j debug
 
;***************************************************************
 
.code
.align 4
 
setcon:
j setcio
 
cinchk:
j cichk
 
cin:
j ci
 
coutchk:
j cochk
 
cout:
j co
 
dskcap:
j dcap
 
dskio:
j dio
 
reserved_11:
j reserved_11
 
reserved_12:
j reserved_12
 
reserved_13:
j reserved_13
 
reserved_14:
j reserved_14
 
reserved_15:
j reserved_15
 
;***************************************************************
 
.code
.align 4
 
start:
; let irq/exc vectors point to RAM
add $8,$0,V
mvts $8,PSW
 
; disable flash ROM, enable SPI bus
add $8,$0,BIO_WR
add $9,$0,SPI_EN
stw $9,$8,0
 
; initialize TLB
mvts $0,TLB_ENTRY_LO ; invalidate all TLB entries
add $8,$0,dmapaddr ; by impossible virtual page number
mvts $8,TLB_ENTRY_HI
add $8,$0,$0
add $9,$0,TLB_ENTRIES
tlbloop:
mvts $8,TLB_INDEX
tbwi
add $8,$8,1
bne $8,$9,tlbloop
 
; copy data segment
add $10,$0,_bdata ; lowest dst addr to be written to
add $8,$0,_edata ; one above the top dst addr
sub $9,$8,$10 ; $9 = size of data segment
add $9,$9,_ecode ; data is waiting right after code
j cpytest
cpyloop:
ldw $11,$9,0 ; src addr in $9
stw $11,$8,0 ; dst addr in $8
cpytest:
sub $8,$8,4 ; downward
sub $9,$9,4
bgeu $8,$10,cpyloop
 
; clear bss segment
add $8,$0,_bbss ; start with first word of bss
add $9,$0,_ebss ; this is one above the top
j clrtest
clrloop:
stw $0,$8,0 ; dst addr in $8
add $8,$8,4 ; upward
clrtest:
bltu $8,$9,clrloop
 
; initialize I/O
add $29,$0,stacktop ; setup monitor stack
jal kbdinit ; init keyboard
jal dspinit ; init display
jal ser0init ; init serial line 0
jal ser1init ; init serial line 1
jal dskinitctl ; init disk (controller)
jal dskinitser ; init disk (serial line)
ldw $8,$0,BIO_RD ; get switch settings
and $8,$8,CIO_CTRL
add $4,$0,CIO_SERIAL_0 ; set console to serial line
bne $8,$0,swtchset
add $4,$0,CIO_KBD_DSP ; set console to kbd/dsp
swtchset:
jal setcio
 
; call main
jal main ; enter command loop
 
; main should never return
j start ; just to be sure...
 
;***************************************************************
 
.code
.align 4
 
; Word getTLB_HI(int index)
getTLB_HI:
mvts $4,TLB_INDEX
tbri
mvfs $2,TLB_ENTRY_HI
jr $31
 
; Word getTLB_LO(int index)
getTLB_LO:
mvts $4,TLB_INDEX
tbri
mvfs $2,TLB_ENTRY_LO
jr $31
 
; void setTLB(int index, Word entryHi, Word entryLo)
setTLB:
mvts $4,TLB_INDEX
mvts $5,TLB_ENTRY_HI
mvts $6,TLB_ENTRY_LO
tbwi
jr $31
 
;***************************************************************
 
.data
.align 4
 
cioctl:
.byte 0
 
.code
.align 4
 
; void setcon(Byte ctl)
setcio:
stb $4,$0,cioctl
j $31
 
; int cinchk(void)
cichk:
ldbu $8,$0,cioctl
and $8,$8,0x01
bne $8,$0,cichk1
j kbdinchk
cichk1:
j ser0inchk
 
; char cin(void)
ci:
ldbu $8,$0,cioctl
and $8,$8,0x01
bne $8,$0,ci1
j kbdin
ci1:
j ser0in
 
; int coutchk(void)
cochk:
ldbu $8,$0,cioctl
and $8,$8,0x02
bne $8,$0,cochk1
j dspoutchk
cochk1:
j ser0outchk
 
; void cout(char c)
co:
ldbu $8,$0,cioctl
and $8,$8,0x02
bne $8,$0,co1
j dspout
co1:
j ser0out
 
;***************************************************************
 
.code
.align 4
 
; int dskcap(int dskno)
dcap:
bne $4,$0,dcapser
j dskcapctl
dcapser:
j dskcapser
 
; int dskio(int dskno, char cmd, int sct, Word addr, int nscts)
dio:
bne $4,$0,dioser
add $4,$5,$0
add $5,$6,$0
add $6,$7,$0
ldw $7,$29,16
j dskioctl
dioser:
add $4,$5,$0
add $5,$6,$0
add $6,$7,$0
ldw $7,$29,16
j dskioser
 
;***************************************************************
 
.code
.align 4
 
; Bool saveState(MonitorState *msp)
; always return 'true' here
saveState:
stw $31,$4,0*4 ; return address
stw $29,$4,1*4 ; stack pointer
stw $16,$4,2*4 ; local variables
stw $17,$4,3*4
stw $18,$4,4*4
stw $19,$4,5*4
stw $20,$4,6*4
stw $21,$4,7*4
stw $22,$4,8*4
stw $23,$4,9*4
add $2,$0,1
jr $31
 
; load state when re-entering monitor
; this appears as if returning from saveState
; but the return value is 'false' here
loadState:
ldw $8,$0,monitorReturn
beq $8,$0,loadState ; fatal error: monitor state lost
ldw $31,$8,0*4 ; return address
ldw $29,$8,1*4 ; stack pointer
ldw $16,$8,2*4 ; local variables
ldw $17,$8,3*4
ldw $18,$8,4*4
ldw $19,$8,5*4
ldw $20,$8,6*4
ldw $21,$8,7*4
ldw $22,$8,8*4
ldw $23,$8,9*4
add $2,$0,0
jr $31
 
.bss
.align 4
 
; extern MonitorState *monitorReturn
monitorReturn:
.space 4
 
; extern UserContext userContext
userContext:
.space USER_CONTEXT_SIZE
 
;***************************************************************
 
.code
.align 4
 
; void resume(void)
; use userContext to load state
resume:
mvts $0,PSW
add $24,$0,userContext
.nosyn
ldw $8,$24,33*4 ; tlbIndex
mvts $8,TLB_INDEX
ldw $8,$24,34*4 ; tlbEntryHi
mvts $8,TLB_ENTRY_HI
ldw $8,$24,35*4 ; tlbEntryLo
mvts $8,TLB_ENTRY_LO
ldw $8,$24,36*4 ; badAddress
mvts $8,BAD_ADDRESS
ldw $8,$24,37*4 ; badAccess
mvts $8,BAD_ACCESS
;ldw $0,$24,0*4 ; registers
ldw $1,$24,1*4
ldw $2,$24,2*4
ldw $3,$24,3*4
ldw $4,$24,4*4
ldw $5,$24,5*4
ldw $6,$24,6*4
ldw $7,$24,7*4
ldw $8,$24,8*4
ldw $9,$24,9*4
ldw $10,$24,10*4
ldw $11,$24,11*4
ldw $12,$24,12*4
ldw $13,$24,13*4
ldw $14,$24,14*4
ldw $15,$24,15*4
ldw $16,$24,16*4
ldw $17,$24,17*4
ldw $18,$24,18*4
ldw $19,$24,19*4
ldw $20,$24,20*4
ldw $21,$24,21*4
ldw $22,$24,22*4
ldw $23,$24,23*4
;ldw $24,$24,24*4
ldw $25,$24,25*4
ldw $26,$24,26*4
ldw $27,$24,27*4
ldw $28,$24,28*4
ldw $29,$24,29*4
ldw $30,$24,30*4
ldw $31,$24,31*4
ldw $24,$24,32*4 ; psw
mvts $24,PSW
rfx
.syn
 
; debug entry
; use userContext to store state
debug:
.nosyn
ldhi $24,userContext
or $24,$24,userContext
stw $0,$24,0*4 ; registers
stw $1,$24,1*4
stw $2,$24,2*4
stw $3,$24,3*4
stw $4,$24,4*4
stw $5,$24,5*4
stw $6,$24,6*4
stw $7,$24,7*4
stw $8,$24,8*4
stw $9,$24,9*4
stw $10,$24,10*4
stw $11,$24,11*4
stw $12,$24,12*4
stw $13,$24,13*4
stw $14,$24,14*4
stw $15,$24,15*4
stw $16,$24,16*4
stw $17,$24,17*4
stw $18,$24,18*4
stw $19,$24,19*4
stw $20,$24,20*4
stw $21,$24,21*4
stw $22,$24,22*4
stw $23,$24,23*4
stw $24,$24,24*4
stw $25,$24,25*4
stw $26,$24,26*4
stw $27,$24,27*4
stw $28,$24,28*4
stw $29,$24,29*4
stw $30,$24,30*4
stw $31,$24,31*4
mvfs $8,PSW
stw $8,$24,32*4 ; psw
mvfs $8,TLB_INDEX
stw $8,$24,33*4 ; tlbIndex
mvfs $8,TLB_ENTRY_HI
stw $8,$24,34*4 ; tlbEntryHi
mvfs $8,TLB_ENTRY_LO
stw $8,$24,35*4 ; tlbEntryLo
mvfs $8,BAD_ADDRESS
stw $8,$24,36*4 ; badAddress
mvfs $8,BAD_ACCESS
stw $8,$24,37*4 ; badAccess
.syn
j loadState
/boards/s3e-500/Makefile
0,0 → 1,50
#
# Makefile for ECO32 ROM monitor
#
 
BUILD = ../../../../build
 
SRC = start.s \
../../common/main.c \
../../common/command.c \
../../common/instr.c \
../../common/asm.c \
../../common/disasm.c \
../../common/load.c \
../../common/boot.c \
../../common/cpu.c \
../../common/mmu.c \
../../common/getline.c \
../../common/romlib.c \
../../common/keyboard.s \
../../kbdtbls/kbdtbls.s \
../../common/display.s \
../../common/serial.s \
../../common/dskctl.s \
../../common/dskser.s \
../../common/end.s
 
.PHONY: all install clean
 
all: monitor.bin monitor.mcs
 
install: monitor.bin monitor.mcs
mkdir -p $(BUILD)/monitor/s3e-500
cp monitor.bin $(BUILD)/monitor/s3e-500
cp monitor.mcs $(BUILD)/monitor/s3e-500
 
monitor.mcs: monitor.bin
$(BUILD)/bin/bin2mcs 0x00000000 monitor.bin monitor.mcs
 
monitor.bin: $(SRC)
$(BUILD)/bin/lcc -A -Wo-rom -Wl-rc -Wl0xC0000000 \
-Wl-rd -Wl0xC000C000 \
-Wl-m -Wlmonitor.map \
-o prelim.bin $(SRC)
cat ../../copy/copy.bin prelim.bin >monitor.bin
rm prelim.bin
 
clean:
rm -f *~
rm -f prelim.bin monitor.map monitor.bin
rm -f monitor.mcs
/boards/simulator/start.s
0,0 → 1,480
;
; start.s -- ECO32 ROM monitor startup and support routines
;
 
; .set CIO_CTL,0x00 ; set console to keyboard/display
.set CIO_CTL,0x03 ; set console to serial line 0
 
.set dmapaddr,0xC0000000 ; base of directly mapped addresses
.set stacktop,0xC0010000 ; monitor stack is at top of 64K
 
.set PSW,0 ; reg # of PSW
.set V_SHIFT,27 ; interrupt vector ctrl bit
.set V,1 << V_SHIFT
 
.set TLB_INDEX,1 ; reg # of TLB Index
.set TLB_ENTRY_HI,2 ; reg # of TLB EntryHi
.set TLB_ENTRY_LO,3 ; reg # of TLB EntryLo
.set TLB_ENTRIES,32 ; number of TLB entries
.set BAD_ADDRESS,4 ; reg # of bad address reg
.set BAD_ACCESS,5 ; reg # of bad access reg
 
.set USER_CONTEXT_SIZE,38*4 ; size of user context
 
;***************************************************************
 
.import _ecode
.import _edata
.import _ebss
 
.import kbdinit
.import kbdinchk
.import kbdin
 
.import dspinit
.import dspoutchk
.import dspout
 
.import ser0init
.import ser0inchk
.import ser0in
.import ser0outchk
.import ser0out
 
.import ser1init
.import ser1inchk
.import ser1in
.import ser1outchk
.import ser1out
 
.import dskinitctl
.import dskcapctl
.import dskioctl
 
.import dskinitser
.import dskcapser
.import dskioser
 
.import main
 
.export _bcode
.export _bdata
.export _bbss
 
.export setcon
.export cinchk
.export cin
.export coutchk
.export cout
.export dskcap
.export dskio
 
.export getTLB_HI
.export getTLB_LO
.export setTLB
 
.export saveState
.export monitorReturn
 
.import userContext
.export resume
 
;***************************************************************
 
.code
_bcode:
 
.data
_bdata:
 
.bss
_bbss:
 
;***************************************************************
 
.code
.align 4
 
startup:
j start
 
interrupt:
j debug
 
userMiss:
j debug
 
monitor:
j debug
 
;***************************************************************
 
.code
.align 4
 
setcon:
j setcio
 
cinchk:
j cichk
 
cin:
j ci
 
coutchk:
j cochk
 
cout:
j co
 
dskcap:
j dcap
 
dskio:
j dio
 
reserved_11:
j reserved_11
 
reserved_12:
j reserved_12
 
reserved_13:
j reserved_13
 
reserved_14:
j reserved_14
 
reserved_15:
j reserved_15
 
;***************************************************************
 
.code
.align 4
 
start:
; let irq/exc vectors point to RAM
add $8,$0,V
mvts $8,PSW
 
; initialize TLB
mvts $0,TLB_ENTRY_LO ; invalidate all TLB entries
add $8,$0,dmapaddr ; by impossible virtual page number
mvts $8,TLB_ENTRY_HI
add $8,$0,$0
add $9,$0,TLB_ENTRIES
tlbloop:
mvts $8,TLB_INDEX
tbwi
add $8,$8,1
bne $8,$9,tlbloop
 
; copy data segment
add $10,$0,_bdata ; lowest dst addr to be written to
add $8,$0,_edata ; one above the top dst addr
sub $9,$8,$10 ; $9 = size of data segment
add $9,$9,_ecode ; data is waiting right after code
j cpytest
cpyloop:
ldw $11,$9,0 ; src addr in $9
stw $11,$8,0 ; dst addr in $8
cpytest:
sub $8,$8,4 ; downward
sub $9,$9,4
bgeu $8,$10,cpyloop
 
; clear bss segment
add $8,$0,_bbss ; start with first word of bss
add $9,$0,_ebss ; this is one above the top
j clrtest
clrloop:
stw $0,$8,0 ; dst addr in $8
add $8,$8,4 ; upward
clrtest:
bltu $8,$9,clrloop
 
; initialize I/O
add $29,$0,stacktop ; setup monitor stack
jal kbdinit ; init keyboard
jal dspinit ; init display
jal ser0init ; init serial line 0
jal ser1init ; init serial line 1
jal dskinitctl ; init disk (controller)
jal dskinitser ; init disk (serial line)
add $4,$0,CIO_CTL ; set console
jal setcio
 
; call main
jal main ; enter command loop
 
; main should never return
j start ; just to be sure...
 
;***************************************************************
 
.code
.align 4
 
; Word getTLB_HI(int index)
getTLB_HI:
mvts $4,TLB_INDEX
tbri
mvfs $2,TLB_ENTRY_HI
jr $31
 
; Word getTLB_LO(int index)
getTLB_LO:
mvts $4,TLB_INDEX
tbri
mvfs $2,TLB_ENTRY_LO
jr $31
 
; void setTLB(int index, Word entryHi, Word entryLo)
setTLB:
mvts $4,TLB_INDEX
mvts $5,TLB_ENTRY_HI
mvts $6,TLB_ENTRY_LO
tbwi
jr $31
 
;***************************************************************
 
.data
.align 4
 
cioctl:
.byte 0
 
.code
.align 4
 
; void setcon(Byte ctl)
setcio:
stb $4,$0,cioctl
j $31
 
; int cinchk(void)
cichk:
ldbu $8,$0,cioctl
and $8,$8,0x01
bne $8,$0,cichk1
j kbdinchk
cichk1:
j ser0inchk
 
; char cin(void)
ci:
ldbu $8,$0,cioctl
and $8,$8,0x01
bne $8,$0,ci1
j kbdin
ci1:
j ser0in
 
; int coutchk(void)
cochk:
ldbu $8,$0,cioctl
and $8,$8,0x02
bne $8,$0,cochk1
j dspoutchk
cochk1:
j ser0outchk
 
; void cout(char c)
co:
ldbu $8,$0,cioctl
and $8,$8,0x02
bne $8,$0,co1
j dspout
co1:
j ser0out
 
;***************************************************************
 
.code
.align 4
 
; int dskcap(int dskno)
dcap:
bne $4,$0,dcapser
j dskcapctl
dcapser:
j dskcapser
 
; int dskio(int dskno, char cmd, int sct, Word addr, int nscts)
dio:
bne $4,$0,dioser
add $4,$5,$0
add $5,$6,$0
add $6,$7,$0
ldw $7,$29,16
j dskioctl
dioser:
add $4,$5,$0
add $5,$6,$0
add $6,$7,$0
ldw $7,$29,16
j dskioser
 
;***************************************************************
 
.code
.align 4
 
; Bool saveState(MonitorState *msp)
; always return 'true' here
saveState:
stw $31,$4,0*4 ; return address
stw $29,$4,1*4 ; stack pointer
stw $16,$4,2*4 ; local variables
stw $17,$4,3*4
stw $18,$4,4*4
stw $19,$4,5*4
stw $20,$4,6*4
stw $21,$4,7*4
stw $22,$4,8*4
stw $23,$4,9*4
add $2,$0,1
jr $31
 
; load state when re-entering monitor
; this appears as if returning from saveState
; but the return value is 'false' here
loadState:
ldw $8,$0,monitorReturn
beq $8,$0,loadState ; fatal error: monitor state lost
ldw $31,$8,0*4 ; return address
ldw $29,$8,1*4 ; stack pointer
ldw $16,$8,2*4 ; local variables
ldw $17,$8,3*4
ldw $18,$8,4*4
ldw $19,$8,5*4
ldw $20,$8,6*4
ldw $21,$8,7*4
ldw $22,$8,8*4
ldw $23,$8,9*4
add $2,$0,0
jr $31
 
.bss
.align 4
 
; extern MonitorState *monitorReturn
monitorReturn:
.space 4
 
; extern UserContext userContext
userContext:
.space USER_CONTEXT_SIZE
 
;***************************************************************
 
.code
.align 4
 
; void resume(void)
; use userContext to load state
resume:
mvts $0,PSW
add $24,$0,userContext
.nosyn
ldw $8,$24,33*4 ; tlbIndex
mvts $8,TLB_INDEX
ldw $8,$24,34*4 ; tlbEntryHi
mvts $8,TLB_ENTRY_HI
ldw $8,$24,35*4 ; tlbEntryLo
mvts $8,TLB_ENTRY_LO
ldw $8,$24,36*4 ; badAddress
mvts $8,BAD_ADDRESS
ldw $8,$24,37*4 ; badAccess
mvts $8,BAD_ACCESS
;ldw $0,$24,0*4 ; registers
ldw $1,$24,1*4
ldw $2,$24,2*4
ldw $3,$24,3*4
ldw $4,$24,4*4
ldw $5,$24,5*4
ldw $6,$24,6*4
ldw $7,$24,7*4
ldw $8,$24,8*4
ldw $9,$24,9*4
ldw $10,$24,10*4
ldw $11,$24,11*4
ldw $12,$24,12*4
ldw $13,$24,13*4
ldw $14,$24,14*4
ldw $15,$24,15*4
ldw $16,$24,16*4
ldw $17,$24,17*4
ldw $18,$24,18*4
ldw $19,$24,19*4
ldw $20,$24,20*4
ldw $21,$24,21*4
ldw $22,$24,22*4
ldw $23,$24,23*4
;ldw $24,$24,24*4
ldw $25,$24,25*4
ldw $26,$24,26*4
ldw $27,$24,27*4
ldw $28,$24,28*4
ldw $29,$24,29*4
ldw $30,$24,30*4
ldw $31,$24,31*4
ldw $24,$24,32*4 ; psw
mvts $24,PSW
rfx
.syn
 
; debug entry
; use userContext to store state
debug:
.nosyn
ldhi $24,userContext
or $24,$24,userContext
stw $0,$24,0*4 ; registers
stw $1,$24,1*4
stw $2,$24,2*4
stw $3,$24,3*4
stw $4,$24,4*4
stw $5,$24,5*4
stw $6,$24,6*4
stw $7,$24,7*4
stw $8,$24,8*4
stw $9,$24,9*4
stw $10,$24,10*4
stw $11,$24,11*4
stw $12,$24,12*4
stw $13,$24,13*4
stw $14,$24,14*4
stw $15,$24,15*4
stw $16,$24,16*4
stw $17,$24,17*4
stw $18,$24,18*4
stw $19,$24,19*4
stw $20,$24,20*4
stw $21,$24,21*4
stw $22,$24,22*4
stw $23,$24,23*4
stw $24,$24,24*4
stw $25,$24,25*4
stw $26,$24,26*4
stw $27,$24,27*4
stw $28,$24,28*4
stw $29,$24,29*4
stw $30,$24,30*4
stw $31,$24,31*4
mvfs $8,PSW
stw $8,$24,32*4 ; psw
mvfs $8,TLB_INDEX
stw $8,$24,33*4 ; tlbIndex
mvfs $8,TLB_ENTRY_HI
stw $8,$24,34*4 ; tlbEntryHi
mvfs $8,TLB_ENTRY_LO
stw $8,$24,35*4 ; tlbEntryLo
mvfs $8,BAD_ADDRESS
stw $8,$24,36*4 ; badAddress
mvfs $8,BAD_ACCESS
stw $8,$24,37*4 ; badAccess
.syn
j loadState
/boards/simulator/Makefile
0,0 → 1,45
#
# Makefile for ECO32 ROM monitor
#
 
BUILD = ../../../../build
 
SRC = start.s \
../../common/main.c \
../../common/command.c \
../../common/instr.c \
../../common/asm.c \
../../common/disasm.c \
../../common/load.c \
../../common/boot.c \
../../common/cpu.c \
../../common/mmu.c \
../../common/getline.c \
../../common/romlib.c \
../../common/keyboard.s \
../../kbdtbls/kbdtbls.s \
../../common/display.s \
../../common/serial.s \
../../common/dskctl.s \
../../common/dskser.s \
../../common/end.s
 
.PHONY: all install clean
 
all: monitor.bin
 
install: monitor.bin
mkdir -p $(BUILD)/monitor/simulator
cp monitor.bin $(BUILD)/monitor/simulator
 
monitor.bin: $(SRC)
$(BUILD)/bin/lcc -A -Wo-rom -Wl-rc -Wl0xC0000000 \
-Wl-rd -Wl0xC000C000 \
-Wl-m -Wlmonitor.map \
-o prelim.bin $(SRC)
cat ../../copy/copy.bin prelim.bin >monitor.bin
rm prelim.bin
 
clean:
rm -f *~
rm -f prelim.bin monitor.map monitor.bin
/boards/xsa-xst-3/start.s
0,0 → 1,490
;
; start.s -- ECO32 ROM monitor startup and support routines
;
 
.set BIO_BASE,0xF1000000 ; board I/O base address
.set BIO_WR,BIO_BASE+0
.set BIO_RD,BIO_BASE+4
.set CIO_CTRL,0x08 ; this bit controls console I/O
 
.set CIO_KBD_DSP,0x00 ; set console to keyboard/display
.set CIO_SERIAL_0,0x03 ; set console to serial line 0
 
.set dmapaddr,0xC0000000 ; base of directly mapped addresses
.set stacktop,0xC0010000 ; monitor stack is at top of 64K
 
.set PSW,0 ; reg # of PSW
.set V_SHIFT,27 ; interrupt vector ctrl bit
.set V,1 << V_SHIFT
 
.set TLB_INDEX,1 ; reg # of TLB Index
.set TLB_ENTRY_HI,2 ; reg # of TLB EntryHi
.set TLB_ENTRY_LO,3 ; reg # of TLB EntryLo
.set TLB_ENTRIES,32 ; number of TLB entries
.set BAD_ADDRESS,4 ; reg # of bad address reg
.set BAD_ACCESS,5 ; reg # of bad access reg
 
.set USER_CONTEXT_SIZE,38*4 ; size of user context
 
;***************************************************************
 
.import _ecode
.import _edata
.import _ebss
 
.import kbdinit
.import kbdinchk
.import kbdin
 
.import dspinit
.import dspoutchk
.import dspout
 
.import ser0init
.import ser0inchk
.import ser0in
.import ser0outchk
.import ser0out
 
.import ser1init
.import ser1inchk
.import ser1in
.import ser1outchk
.import ser1out
 
.import dskinitctl
.import dskcapctl
.import dskioctl
 
.import dskinitser
.import dskcapser
.import dskioser
 
.import main
 
.export _bcode
.export _bdata
.export _bbss
 
.export setcon
.export cinchk
.export cin
.export coutchk
.export cout
.export dskcap
.export dskio
 
.export getTLB_HI
.export getTLB_LO
.export setTLB
 
.export saveState
.export monitorReturn
 
.import userContext
.export resume
 
;***************************************************************
 
.code
_bcode:
 
.data
_bdata:
 
.bss
_bbss:
 
;***************************************************************
 
.code
.align 4
 
startup:
j start
 
interrupt:
j debug
 
userMiss:
j debug
 
monitor:
j debug
 
;***************************************************************
 
.code
.align 4
 
setcon:
j setcio
 
cinchk:
j cichk
 
cin:
j ci
 
coutchk:
j cochk
 
cout:
j co
 
dskcap:
j dcap
 
dskio:
j dio
 
reserved_11:
j reserved_11
 
reserved_12:
j reserved_12
 
reserved_13:
j reserved_13
 
reserved_14:
j reserved_14
 
reserved_15:
j reserved_15
 
;***************************************************************
 
.code
.align 4
 
start:
; let irq/exc vectors point to RAM
add $8,$0,V
mvts $8,PSW
 
; initialize TLB
mvts $0,TLB_ENTRY_LO ; invalidate all TLB entries
add $8,$0,dmapaddr ; by impossible virtual page number
mvts $8,TLB_ENTRY_HI
add $8,$0,$0
add $9,$0,TLB_ENTRIES
tlbloop:
mvts $8,TLB_INDEX
tbwi
add $8,$8,1
bne $8,$9,tlbloop
 
; copy data segment
add $10,$0,_bdata ; lowest dst addr to be written to
add $8,$0,_edata ; one above the top dst addr
sub $9,$8,$10 ; $9 = size of data segment
add $9,$9,_ecode ; data is waiting right after code
j cpytest
cpyloop:
ldw $11,$9,0 ; src addr in $9
stw $11,$8,0 ; dst addr in $8
cpytest:
sub $8,$8,4 ; downward
sub $9,$9,4
bgeu $8,$10,cpyloop
 
; clear bss segment
add $8,$0,_bbss ; start with first word of bss
add $9,$0,_ebss ; this is one above the top
j clrtest
clrloop:
stw $0,$8,0 ; dst addr in $8
add $8,$8,4 ; upward
clrtest:
bltu $8,$9,clrloop
 
; initialize I/O
add $29,$0,stacktop ; setup monitor stack
jal kbdinit ; init keyboard
jal dspinit ; init display
jal ser0init ; init serial line 0
jal ser1init ; init serial line 1
jal dskinitctl ; init disk (controller)
jal dskinitser ; init disk (serial line)
ldw $8,$0,BIO_RD ; get switch settings
and $8,$8,CIO_CTRL
add $4,$0,CIO_SERIAL_0 ; set console to serial line
bne $8,$0,swtchset
add $4,$0,CIO_KBD_DSP ; set console to kbd/dsp
swtchset:
jal setcio
 
; call main
jal main ; enter command loop
 
; main should never return
j start ; just to be sure...
 
;***************************************************************
 
.code
.align 4
 
; Word getTLB_HI(int index)
getTLB_HI:
mvts $4,TLB_INDEX
tbri
mvfs $2,TLB_ENTRY_HI
jr $31
 
; Word getTLB_LO(int index)
getTLB_LO:
mvts $4,TLB_INDEX
tbri
mvfs $2,TLB_ENTRY_LO
jr $31
 
; void setTLB(int index, Word entryHi, Word entryLo)
setTLB:
mvts $4,TLB_INDEX
mvts $5,TLB_ENTRY_HI
mvts $6,TLB_ENTRY_LO
tbwi
jr $31
 
;***************************************************************
 
.data
.align 4
 
cioctl:
.byte 0
 
.code
.align 4
 
; void setcon(Byte ctl)
setcio:
stb $4,$0,cioctl
j $31
 
; int cinchk(void)
cichk:
ldbu $8,$0,cioctl
and $8,$8,0x01
bne $8,$0,cichk1
j kbdinchk
cichk1:
j ser0inchk
 
; char cin(void)
ci:
ldbu $8,$0,cioctl
and $8,$8,0x01
bne $8,$0,ci1
j kbdin
ci1:
j ser0in
 
; int coutchk(void)
cochk:
ldbu $8,$0,cioctl
and $8,$8,0x02
bne $8,$0,cochk1
j dspoutchk
cochk1:
j ser0outchk
 
; void cout(char c)
co:
ldbu $8,$0,cioctl
and $8,$8,0x02
bne $8,$0,co1
j dspout
co1:
j ser0out
 
;***************************************************************
 
.code
.align 4
 
; int dskcap(int dskno)
dcap:
bne $4,$0,dcapser
j dskcapctl
dcapser:
j dskcapser
 
; int dskio(int dskno, char cmd, int sct, Word addr, int nscts)
dio:
bne $4,$0,dioser
add $4,$5,$0
add $5,$6,$0
add $6,$7,$0
ldw $7,$29,16
j dskioctl
dioser:
add $4,$5,$0
add $5,$6,$0
add $6,$7,$0
ldw $7,$29,16
j dskioser
 
;***************************************************************
 
.code
.align 4
 
; Bool saveState(MonitorState *msp)
; always return 'true' here
saveState:
stw $31,$4,0*4 ; return address
stw $29,$4,1*4 ; stack pointer
stw $16,$4,2*4 ; local variables
stw $17,$4,3*4
stw $18,$4,4*4
stw $19,$4,5*4
stw $20,$4,6*4
stw $21,$4,7*4
stw $22,$4,8*4
stw $23,$4,9*4
add $2,$0,1
jr $31
 
; load state when re-entering monitor
; this appears as if returning from saveState
; but the return value is 'false' here
loadState:
ldw $8,$0,monitorReturn
beq $8,$0,loadState ; fatal error: monitor state lost
ldw $31,$8,0*4 ; return address
ldw $29,$8,1*4 ; stack pointer
ldw $16,$8,2*4 ; local variables
ldw $17,$8,3*4
ldw $18,$8,4*4
ldw $19,$8,5*4
ldw $20,$8,6*4
ldw $21,$8,7*4
ldw $22,$8,8*4
ldw $23,$8,9*4
add $2,$0,0
jr $31
 
.bss
.align 4
 
; extern MonitorState *monitorReturn
monitorReturn:
.space 4
 
; extern UserContext userContext
userContext:
.space USER_CONTEXT_SIZE
 
;***************************************************************
 
.code
.align 4
 
; void resume(void)
; use userContext to load state
resume:
mvts $0,PSW
add $24,$0,userContext
.nosyn
ldw $8,$24,33*4 ; tlbIndex
mvts $8,TLB_INDEX
ldw $8,$24,34*4 ; tlbEntryHi
mvts $8,TLB_ENTRY_HI
ldw $8,$24,35*4 ; tlbEntryLo
mvts $8,TLB_ENTRY_LO
ldw $8,$24,36*4 ; badAddress
mvts $8,BAD_ADDRESS
ldw $8,$24,37*4 ; badAccess
mvts $8,BAD_ACCESS
;ldw $0,$24,0*4 ; registers
ldw $1,$24,1*4
ldw $2,$24,2*4
ldw $3,$24,3*4
ldw $4,$24,4*4
ldw $5,$24,5*4
ldw $6,$24,6*4
ldw $7,$24,7*4
ldw $8,$24,8*4
ldw $9,$24,9*4
ldw $10,$24,10*4
ldw $11,$24,11*4
ldw $12,$24,12*4
ldw $13,$24,13*4
ldw $14,$24,14*4
ldw $15,$24,15*4
ldw $16,$24,16*4
ldw $17,$24,17*4
ldw $18,$24,18*4
ldw $19,$24,19*4
ldw $20,$24,20*4
ldw $21,$24,21*4
ldw $22,$24,22*4
ldw $23,$24,23*4
;ldw $24,$24,24*4
ldw $25,$24,25*4
ldw $26,$24,26*4
ldw $27,$24,27*4
ldw $28,$24,28*4
ldw $29,$24,29*4
ldw $30,$24,30*4
ldw $31,$24,31*4
ldw $24,$24,32*4 ; psw
mvts $24,PSW
rfx
.syn
 
; debug entry
; use userContext to store state
debug:
.nosyn
ldhi $24,userContext
or $24,$24,userContext
stw $0,$24,0*4 ; registers
stw $1,$24,1*4
stw $2,$24,2*4
stw $3,$24,3*4
stw $4,$24,4*4
stw $5,$24,5*4
stw $6,$24,6*4
stw $7,$24,7*4
stw $8,$24,8*4
stw $9,$24,9*4
stw $10,$24,10*4
stw $11,$24,11*4
stw $12,$24,12*4
stw $13,$24,13*4
stw $14,$24,14*4
stw $15,$24,15*4
stw $16,$24,16*4
stw $17,$24,17*4
stw $18,$24,18*4
stw $19,$24,19*4
stw $20,$24,20*4
stw $21,$24,21*4
stw $22,$24,22*4
stw $23,$24,23*4
stw $24,$24,24*4
stw $25,$24,25*4
stw $26,$24,26*4
stw $27,$24,27*4
stw $28,$24,28*4
stw $29,$24,29*4
stw $30,$24,30*4
stw $31,$24,31*4
mvfs $8,PSW
stw $8,$24,32*4 ; psw
mvfs $8,TLB_INDEX
stw $8,$24,33*4 ; tlbIndex
mvfs $8,TLB_ENTRY_HI
stw $8,$24,34*4 ; tlbEntryHi
mvfs $8,TLB_ENTRY_LO
stw $8,$24,35*4 ; tlbEntryLo
mvfs $8,BAD_ADDRESS
stw $8,$24,36*4 ; badAddress
mvfs $8,BAD_ACCESS
stw $8,$24,37*4 ; badAccess
.syn
j loadState
/boards/xsa-xst-3/Makefile
0,0 → 1,50
#
# Makefile for ECO32 ROM monitor
#
 
BUILD = ../../../../build
 
SRC = start.s \
../../common/main.c \
../../common/command.c \
../../common/instr.c \
../../common/asm.c \
../../common/disasm.c \
../../common/load.c \
../../common/boot.c \
../../common/cpu.c \
../../common/mmu.c \
../../common/getline.c \
../../common/romlib.c \
../../common/keyboard.s \
../../kbdtbls/kbdtbls.s \
../../common/display.s \
../../common/serial.s \
../../common/dskctl.s \
../../common/dskser.s \
../../common/end.s
 
.PHONY: all install clean
 
all: monitor.bin monitor.exo
 
install: monitor.bin monitor.exo
mkdir -p $(BUILD)/monitor/xsa-xst-3
cp monitor.bin $(BUILD)/monitor/xsa-xst-3
cp monitor.exo $(BUILD)/monitor/xsa-xst-3
 
monitor.exo: monitor.bin
$(BUILD)/bin/bin2exo -S2 0 monitor.bin monitor.exo
 
monitor.bin: $(SRC)
$(BUILD)/bin/lcc -A -Wo-rom -Wl-rc -Wl0xC0000000 \
-Wl-rd -Wl0xC000C000 \
-Wl-m -Wlmonitor.map \
-o prelim.bin $(SRC)
cat ../../copy/copy.bin prelim.bin >monitor.bin
rm prelim.bin
 
clean:
rm -f *~
rm -f prelim.bin monitor.map monitor.bin
rm -f monitor.exo
/boards/Makefile
0,0 → 1,25
#
# Makefile for building the ECO32 ROM monitor for different boards
#
 
BUILD = ../../../build
 
DIRS = simulator xsa-xst-3 s3e-500
 
.PHONY: all install clean
 
all:
for i in $(DIRS) ; do \
$(MAKE) -C $$i all ; \
done
 
install:
for i in $(DIRS) ; do \
$(MAKE) -C $$i install ; \
done
 
clean:
for i in $(DIRS) ; do \
$(MAKE) -C $$i clean ; \
done
rm -f *~
/common/command.c
0,0 → 1,917
/*
* command.c -- command interpreter
*/
 
 
#include "common.h"
#include "stdarg.h"
#include "romlib.h"
#include "getline.h"
#include "command.h"
#include "asm.h"
#include "disasm.h"
#include "load.h"
#include "boot.h"
#include "cpu.h"
#include "mmu.h"
#include "start.h"
 
 
#define MAX_TOKENS 10
 
 
typedef struct {
char *name;
void (*hlpProc)(void);
void (*cmdProc)(char *tokens[], int n);
} Command;
 
extern Command commands[];
extern int numCommands;
 
 
static void help(void) {
printf("valid commands are:\n");
printf(" help get help\n");
printf(" + add and subtract\n");
printf(" a assemble\n");
printf(" u unassemble\n");
printf(" b set/reset breakpoint\n");
printf(" c continue from breakpoint\n");
printf(" s single-step\n");
printf(" # show/set PC\n");
printf(" p show/set PSW\n");
printf(" r show/set register\n");
printf(" d dump memory\n");
printf(" mw show/set memory word\n");
printf(" mh show/set memory halfword\n");
printf(" mb show/set memory byte\n");
printf(" t show/set TLB contents\n");
printf(" load load from serial line\n");
printf(" boot bootstrap from disk\n");
printf("type 'help <cmd>' to get help for <cmd>\n");
}
 
 
static void help00(void) {
printf(" help show a list of commands\n");
printf(" help <cmd> show help for <cmd>\n");
}
 
 
static void help01(void) {
printf(" + <num1> <num2> add and subtract <num1> and <num2>\n");
}
 
 
static void help02(void) {
printf(" a assemble starting at PC\n");
printf(" a <addr> assemble starting at <addr>\n");
}
 
 
static void help03(void) {
printf(" u unassemble 16 instrs starting at PC\n");
printf(" u <addr> unassemble 16 instrs starting at <addr>\n");
printf(" u <addr> <cnt> unassemble <cnt> instrs starting at <addr>\n");
}
 
 
static void help04(void) {
printf(" b reset break\n");
printf(" b <addr> set break at <addr>\n");
}
 
 
static void help05(void) {
printf(" c continue execution\n");
printf(" c <cnt> continue execution <cnt> times\n");
}
 
 
static void help06(void) {
printf(" s single-step one instruction\n");
printf(" s <cnt> single-step <cnt> instructions\n");
}
 
 
static void help07(void) {
printf(" # show PC\n");
printf(" # <addr> set PC to <addr>\n");
}
 
 
static void help08(void) {
printf(" p show PSW\n");
printf(" p <data> set PSW to <data>\n");
}
 
 
static void help09(void) {
printf(" r show all registers\n");
printf(" r <reg> show register <reg>\n");
printf(" r <reg> <data> set register <reg> to <data>\n");
}
 
 
static void help10(void) {
printf(" d dump 256 bytes starting at PC\n");
printf(" d <addr> dump 256 bytes starting at <addr>\n");
printf(" d <addr> <cnt> dump <cnt> bytes starting at <addr>\n");
}
 
 
static void help11(void) {
printf(" mw show memory word at PC\n");
printf(" mw <addr> show memory word at <addr>\n");
printf(" mw <addr> <data> set memory word at <addr> to <data>\n");
}
 
 
static void help12(void) {
printf(" mh show memory halfword at PC\n");
printf(" mh <addr> show memory halfword at <addr>\n");
printf(" mh <addr> <data> set memory halfword at <addr> to <data>\n");
}
 
 
static void help13(void) {
printf(" mb show memory byte at PC\n");
printf(" mb <addr> show memory byte at <addr>\n");
printf(" mb <addr> <data> set memory byte at <addr> to <data>\n");
}
 
 
static void help14(void) {
printf(" t show TLB contents\n");
printf(" t <i> show TLB contents at <i>\n");
printf(" t <i> p <data> set TLB contents at <i> to page <data>\n");
printf(" t <i> f <data> set TLB contents at <i> to frame <data>\n");
}
 
 
static void help15(void) {
printf(" load <n> load/start S-records from serial line <n>\n");
printf(" load <n> * load S-records from serial line <n>\n");
}
 
 
static void help16(void) {
printf(" boot <n> load/start first sector of disk <n>\n");
printf(" boot <n> * load first sector of disk <n>\n");
}
 
 
static Bool getHexNumber(char *str, Word *valptr) {
char *end;
 
*valptr = strtoul(str, &end, 16);
return *end == '\0';
}
 
 
static Bool getDecNumber(char *str, int *valptr) {
char *end;
 
*valptr = strtoul(str, &end, 10);
return *end == '\0';
}
 
 
static void showPC(void) {
Word pc, psw;
Word instr;
 
pc = cpuGetPC();
psw = cpuGetPSW();
instr = mmuReadWord(pc);
printf("PC %08X [PC] %08X %s\n",
pc, instr, disasm(instr, pc));
}
 
 
static void showBreak(void) {
Word brk;
 
brk = cpuGetBreak();
printf("brk ");
if (cpuTestBreak()) {
printf("%08X", brk);
} else {
printf("--------");
}
printf("\n");
}
 
 
static void showPSW(void) {
Word psw;
int i;
 
psw = cpuGetPSW();
printf(" xxxx V UPO IPO IACK MASK\n");
printf("PSW ");
for (i = 31; i >= 0; i--) {
if (i == 27 || i == 26 || i == 23 || i == 20 || i == 15) {
printf(" ");
}
printf("%c", psw & (1 << i) ? '1' : '0');
}
printf("\n");
}
 
 
static void doHelp(char *tokens[], int n) {
int i;
 
if (n == 1) {
help();
} else if (n == 2) {
for (i = 0; i < numCommands; i++) {
if (strcmp(commands[i].name, tokens[1]) == 0) {
(*commands[i].hlpProc)();
return;
}
}
printf("no help available for '%s', sorry\n", tokens[1]);
} else {
help00();
}
}
 
 
static void doArith(char *tokens[], int n) {
Word num1, num2, num3, num4;
 
if (n == 3) {
if (!getHexNumber(tokens[1], &num1)) {
printf("illegal first number\n");
return;
}
if (!getHexNumber(tokens[2], &num2)) {
printf("illegal second number\n");
return;
}
num3 = num1 + num2;
num4 = num1 - num2;
printf("add = %08X, sub = %08X\n", num3, num4);
} else {
help01();
}
}
 
 
static void doAssemble(char *tokens[], int n) {
Word addr;
Word psw;
char prompt[30];
char *line;
char *msg;
Word instr;
 
if (n == 1) {
addr = cpuGetPC();
} else if (n == 2) {
if (!getHexNumber(tokens[1], &addr)) {
printf("illegal address\n");
return;
}
} else {
help02();
return;
}
addr &= ~0x00000003;
psw = cpuGetPSW();
while (1) {
sprintf(prompt, "ASM # %08X: ", addr);
line = getLine(prompt);
if (*line == '\0' || *line == '\n') {
break;
}
addHist(line);
msg = asmInstr(line, addr, &instr);
if (msg != NULL) {
printf("%s\n", msg);
} else {
mmuWriteWord(addr, instr);
addr += 4;
}
}
}
 
 
static void doUnassemble(char *tokens[], int n) {
Word addr, count;
Word psw;
int i;
Word instr;
 
if (n == 1) {
addr = cpuGetPC();
count = 16;
} else if (n == 2) {
if (!getHexNumber(tokens[1], &addr)) {
printf("illegal address\n");
return;
}
count = 16;
} else if (n == 3) {
if (!getHexNumber(tokens[1], &addr)) {
printf("illegal address\n");
return;
}
if (!getHexNumber(tokens[2], &count)) {
printf("illegal count\n");
return;
}
if (count == 0) {
return;
}
} else {
help03();
return;
}
addr &= ~0x00000003;
psw = cpuGetPSW();
for (i = 0; i < count; i++) {
instr = mmuReadWord(addr);
printf("%08X: %08X %s\n",
addr, instr, disasm(instr, addr));
if (addr + 4 < addr) {
/* wrap-around */
break;
}
addr += 4;
}
}
 
 
static void doBreak(char *tokens[], int n) {
Word addr;
 
if (n == 1) {
cpuResetBreak();
showBreak();
} else if (n == 2) {
if (!getHexNumber(tokens[1], &addr)) {
printf("illegal address\n");
return;
}
addr &= ~0x00000003;
cpuSetBreak(addr);
showBreak();
} else {
help04();
}
}
 
 
static void doContinue(char *tokens[], int n) {
Word count, i;
Word addr;
 
if (n == 1) {
count = 1;
} else if (n == 2) {
if (!getHexNumber(tokens[1], &count) || count == 0) {
printf("illegal count\n");
return;
}
} else {
help05();
return;
}
for (i = 0; i < count; i++) {
cpuRun();
}
addr = cpuGetPC();
printf("break at %08X\n", addr);
showPC();
}
 
 
static void doStep(char *tokens[], int n) {
Word count, i;
 
if (n == 1) {
count = 1;
} else if (n == 2) {
if (!getHexNumber(tokens[1], &count) || count == 0) {
printf("illegal count\n");
return;
}
} else {
help06();
return;
}
for (i = 0; i < count; i++) {
cpuStep();
}
showPC();
}
 
 
static void doPC(char *tokens[], int n) {
Word addr;
 
if (n == 1) {
showPC();
} else if (n == 2) {
if (!getHexNumber(tokens[1], &addr)) {
printf("illegal address\n");
return;
}
addr &= ~0x00000003;
cpuSetPC(addr);
showPC();
} else {
help07();
}
}
 
 
static void explainPSW(Word data) {
int i;
 
printf("interrupt vector : %s (%s)\n",
data & PSW_V ? "on " : "off",
data & PSW_V ? "RAM" : "ROM");
printf("current user mode : %s (%s)\n",
data & PSW_UM ? "on " : "off",
data & PSW_UM ? "user" : "kernel");
printf("previous user mode : %s (%s)\n",
data & PSW_PUM ? "on " : "off",
data & PSW_PUM ? "user" : "kernel");
printf("old user mode : %s (%s)\n",
data & PSW_OUM ? "on " : "off",
data & PSW_OUM ? "user" : "kernel");
printf("current interrupt enable : %s (%s)\n",
data & PSW_IE ? "on " : "off",
data & PSW_IE ? "enabled" : "disabled");
printf("previous interrupt enable : %s (%s)\n",
data & PSW_PIE ? "on " : "off",
data & PSW_PIE ? "enabled" : "disabled");
printf("old interrupt enable : %s (%s)\n",
data & PSW_OIE ? "on " : "off",
data & PSW_OIE ? "enabled" : "disabled");
printf("last interrupt acknowledged : %02X (%s)\n",
(data & PSW_PRIO_MASK) >> 16,
exceptionToString((data & PSW_PRIO_MASK) >> 16));
for (i = 15; i >= 0; i--) {
printf("%-35s: %s (%s)\n",
exceptionToString(i),
data & (1 << i) ? "on " : "off",
data & (1 << i) ? "enabled" : "disabled");
}
}
 
 
static void doPSW(char *tokens[], int n) {
Word data;
 
if (n == 1) {
data = cpuGetPSW();
showPSW();
explainPSW(data);
} else if (n == 2) {
if (!getHexNumber(tokens[1], &data)) {
printf("illegal data\n");
return;
}
data &= 0x0FFFFFFF;
cpuSetPSW(data);
showPSW();
explainPSW(data);
} else {
help08();
}
}
 
 
static void doRegister(char *tokens[], int n) {
int i, j;
int reg;
Word data;
 
if (n == 1) {
for (i = 0; i < 8; i++) {
for (j = 0; j < 4; j++) {
reg = 8 * j + i;
data = cpuGetReg(reg);
printf("$%-2d %08X ", reg, data);
}
printf("\n");
}
showPSW();
showBreak();
showPC();
} else if (n == 2) {
if (!getDecNumber(tokens[1], &reg) || reg < 0 || reg >= 32) {
printf("illegal register number\n");
return;
}
data = cpuGetReg(reg);
printf("$%-2d %08X\n", reg, data);
} else if (n == 3) {
if (!getDecNumber(tokens[1], &reg) || reg < 0 || reg >= 32) {
printf("illegal register number\n");
return;
}
if (!getHexNumber(tokens[2], &data)) {
printf("illegal data\n");
return;
}
cpuSetReg(reg, data);
} else {
help09();
}
}
 
 
static void doDump(char *tokens[], int n) {
Word addr, count;
Word psw;
Word lo, hi, curr;
int lines, i, j;
Word tmp;
Byte c;
 
if (n == 1) {
addr = cpuGetPC();
count = 16 * 16;
} else if (n == 2) {
if (!getHexNumber(tokens[1], &addr)) {
printf("illegal address\n");
return;
}
count = 16 * 16;
} else if (n == 3) {
if (!getHexNumber(tokens[1], &addr)) {
printf("illegal address\n");
return;
}
if (!getHexNumber(tokens[2], &count)) {
printf("illegal count\n");
return;
}
if (count == 0) {
return;
}
} else {
help10();
return;
}
psw = cpuGetPSW();
lo = addr & ~0x0000000F;
hi = addr + count - 1;
if (hi < lo) {
/* wrap-around */
hi = 0xFFFFFFFF;
}
lines = (hi - lo + 16) >> 4;
curr = lo;
for (i = 0; i < lines; i++) {
printf("%08X: ", curr);
for (j = 0; j < 16; j++) {
tmp = curr + j;
if (tmp < addr || tmp > hi) {
printf(" ");
} else {
c = mmuReadByte(tmp);
printf("%02X", c);
}
printf(" ");
}
printf(" ");
for (j = 0; j < 16; j++) {
tmp = curr + j;
if (tmp < addr || tmp > hi) {
printf(" ");
} else {
c = mmuReadByte(tmp);
if (c >= 32 && c <= 126) {
printf("%c", c);
} else {
printf(".");
}
}
}
printf("\n");
curr += 16;
}
}
 
 
static void doMemoryWord(char *tokens[], int n) {
Word psw;
Word addr;
Word data;
Word tmpData;
 
psw = cpuGetPSW();
if (n == 1) {
addr = cpuGetPC();
data = mmuReadWord(addr);
printf("%08X: %08X\n", addr, data);
} else if (n == 2) {
if (!getHexNumber(tokens[1], &addr)) {
printf("illegal address\n");
return;
}
data = mmuReadWord(addr);
printf("%08X: %08X\n", addr, data);
} else if (n == 3) {
if (!getHexNumber(tokens[1], &addr)) {
printf("illegal address\n");
return;
}
if (!getHexNumber(tokens[2], &tmpData)) {
printf("illegal data\n");
return;
}
data = tmpData;
mmuWriteWord(addr, data);
} else {
help11();
}
}
 
 
static void doMemoryHalf(char *tokens[], int n) {
Word psw;
Word addr;
Half data;
Word tmpData;
 
psw = cpuGetPSW();
if (n == 1) {
addr = cpuGetPC();
data = mmuReadHalf(addr);
printf("%08X: %04X\n", addr, data);
} else if (n == 2) {
if (!getHexNumber(tokens[1], &addr)) {
printf("illegal address\n");
return;
}
data = mmuReadHalf(addr);
printf("%08X: %04X\n", addr, data);
} else if (n == 3) {
if (!getHexNumber(tokens[1], &addr)) {
printf("illegal address\n");
return;
}
if (!getHexNumber(tokens[2], &tmpData)) {
printf("illegal data\n");
return;
}
data = (Half) tmpData;
mmuWriteHalf(addr, data);
} else {
help12();
}
}
 
 
static void doMemoryByte(char *tokens[], int n) {
Word psw;
Word addr;
Byte data;
Word tmpData;
 
psw = cpuGetPSW();
if (n == 1) {
addr = cpuGetPC();
data = mmuReadByte(addr);
printf("%08X: %02X\n", addr, data);
} else if (n == 2) {
if (!getHexNumber(tokens[1], &addr)) {
printf("illegal address\n");
return;
}
data = mmuReadByte(addr);
printf("%08X: %02X\n", addr, data);
} else if (n == 3) {
if (!getHexNumber(tokens[1], &addr)) {
printf("illegal address\n");
return;
}
if (!getHexNumber(tokens[2], &tmpData)) {
printf("illegal data\n");
return;
}
data = (Byte) tmpData;
mmuWriteByte(addr, data);
} else {
help13();
}
}
 
 
static void doTLB(char *tokens[], int n) {
static char *mmuAccsWidth[4] = { "byte", "half", "word", "????" };
int index;
TLB_Entry tlbEntry;
Word mmuAccs;
Word data;
 
if (n == 1) {
for (index = 0; index < TLB_SIZE; index++) {
tlbEntry = mmuGetTLB(index);
printf("TLB[%02d] page %08X frame %08X %c %c\n",
index, tlbEntry.page, tlbEntry.frame,
tlbEntry.write ? 'w' : '-',
tlbEntry.valid ? 'v' : '-');
}
printf("Index (1) %08X\n", mmuGetIndex());
printf("EntryHi (2) %08X\n", mmuGetEntryHi());
printf("EntryLo (3) %08X\n", mmuGetEntryLo());
printf("BadAddr (4) %08X\n", mmuGetBadAddr());
mmuAccs = mmuGetBadAccs();
printf("BadAccs (5) %08X (%s %s)\n",
mmuAccs,
(mmuAccs & MMU_ACCS_WRITE) ? "write" : "read",
mmuAccsWidth[mmuAccs & 0x03]);
} else if (n == 2) {
if (!getDecNumber(tokens[1], &index) || index < 0 || index >= TLB_SIZE) {
printf("illegal TLB index\n");
return;
}
tlbEntry = mmuGetTLB(index);
printf("TLB[%02d] page %08X frame %08X %c %c\n",
index, tlbEntry.page, tlbEntry.frame,
tlbEntry.write ? 'w' : '-',
tlbEntry.valid ? 'v' : '-');
} else if (n == 3) {
help14();
} else if (n == 4) {
if (!getDecNumber(tokens[1], &index) || index < 0 || index >= TLB_SIZE) {
printf("illegal TLB index\n");
return;
}
if (!getHexNumber(tokens[3], &data)) {
printf("illegal data\n");
return;
}
tlbEntry = mmuGetTLB(index);
if (strcmp(tokens[2], "p") == 0) {
tlbEntry.page = data & PAGE_MASK;
} else
if (strcmp(tokens[2], "f") == 0) {
tlbEntry.frame = data & PAGE_MASK;
tlbEntry.write = data & TLB_WRITE ? true : false;
tlbEntry.valid = data & TLB_VALID ? true : false;
} else {
printf("TLB selector is not one of 'p' or 'f'\n");
return;
}
mmuSetTLB(index, tlbEntry);
printf("TLB[%02d] page %08X frame %08X %c %c\n",
index, tlbEntry.page, tlbEntry.frame,
tlbEntry.write ? 'w' : '-',
tlbEntry.valid ? 'v' : '-');
} else {
help14();
}
}
 
 
static void doLoad(char *tokens[], int n) {
int serno;
 
if (n == 2) {
if (!getDecNumber(tokens[1], &serno) || serno < 0 || serno > 1) {
printf("illegal serial line number\n");
return;
}
load(serno, true);
} else if (n == 3) {
if (!getDecNumber(tokens[1], &serno) || serno < 0 || serno > 1) {
printf("illegal serial line number\n");
return;
}
if (strcmp(tokens[2], "*") != 0) {
help15();
return;
}
load(serno, false);
} else {
help15();
}
}
 
 
static void doBoot(char *tokens[], int n) {
int dskno;
 
if (n == 2) {
if (!getDecNumber(tokens[1], &dskno) || dskno < 0 || dskno > 1) {
printf("illegal disk number\n");
return;
}
boot(dskno, true);
} else if (n == 3) {
if (!getDecNumber(tokens[1], &dskno) || dskno < 0 || dskno > 1) {
printf("illegal disk number\n");
return;
}
if (strcmp(tokens[2], "*") != 0) {
help16();
return;
}
boot(dskno, false);
} else {
help16();
}
}
 
 
Command commands[] = {
{ "help", help00, doHelp },
{ "+", help01, doArith },
{ "a", help02, doAssemble },
{ "u", help03, doUnassemble },
{ "b", help04, doBreak },
{ "c", help05, doContinue },
{ "s", help06, doStep },
{ "#", help07, doPC },
{ "p", help08, doPSW },
{ "r", help09, doRegister },
{ "d", help10, doDump },
{ "mw", help11, doMemoryWord },
{ "mh", help12, doMemoryHalf },
{ "mb", help13, doMemoryByte },
{ "t", help14, doTLB },
{ "load", help15, doLoad },
{ "boot", help16, doBoot },
};
 
int numCommands = sizeof(commands) / sizeof(commands[0]);
 
 
static void doCommand(char *line) {
char *tokens[MAX_TOKENS];
int n;
char *p;
int i;
 
n = 0;
p = strtok(line, " \t\n");
while (p != NULL) {
if (n == MAX_TOKENS) {
printf("too many tokens on line\n");
return;
}
tokens[n++] = p;
p = strtok(NULL, " \t\n");
}
if (n == 0) {
return;
}
for (i = 0; i < numCommands; i++) {
if (strcmp(commands[i].name, tokens[0]) == 0) {
(*commands[i].cmdProc)(tokens, n);
return;
}
}
help();
}
 
 
static char *article(char firstLetterOfNoun) {
switch (firstLetterOfNoun) {
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
return "An";
default:
return "A";
}
}
 
 
static void interactiveException(int exception) {
char *what;
 
what = exceptionToString(exception);
printf("\n");
printf("NOTE: %s %s occurred while executing the command.\n",
article(*what), what);
printf(" This event will not alter the state of the CPU.\n");
}
 
 
void execCommand(char *line) {
MonitorState commandState;
 
if (saveState(&commandState)) {
/* initialization */
monitorReturn = &commandState;
doCommand(line);
} else {
/* an exception was thrown */
interactiveException((userContext.psw & PSW_PRIO_MASK) >> 16);
}
monitorReturn = NULL;
}
/common/load.c
0,0 → 1,226
/*
* load.c -- load S-records from serial line
*/
 
 
#include "common.h"
#include "stdarg.h"
#include "romlib.h"
#include "load.h"
#include "serial.h"
#include "cpu.h"
#include "mmu.h"
 
 
#define NUM_TRIES 10
#define WAIT_DELAY 350000
 
#define SYN ((unsigned char) 's')
#define ACK ((unsigned char) 'a')
 
#define LINE_SIZE 520
 
 
static Byte line[LINE_SIZE];
 
 
static Word getByte(int index) {
Word hi, lo;
 
hi = line[index + 0];
if (hi >= '0' && hi <= '9') {
hi -= '0';
} else
if (hi >= 'A' && hi <= 'F') {
hi -= 'A' - 10;
} else
if (hi >= 'a' && hi <= 'f') {
hi -= 'a' - 10;
} else {
return -1;
}
lo = line[index + 1];
if (lo >= '0' && lo <= '9') {
lo -= '0';
} else
if (lo >= 'A' && lo <= 'F') {
lo -= 'A' - 10;
} else
if (lo >= 'a' && lo <= 'f') {
lo -= 'a' - 10;
} else {
return -1;
}
return (hi << 4) | lo;
}
 
 
static void serialOut(int serno, Word c) {
if (serno == 0) {
ser0out(c);
} else {
ser1out(c);
}
}
 
 
static int serialChk(int serno) {
if (serno == 0) {
return ser0inchk();
} else {
return ser1inchk();
}
}
 
 
static Word serialIn(int serno) {
if (serno == 0) {
return ser0in();
} else {
return ser1in();
}
}
 
 
void load(int serno, Bool start) {
int i, j;
Bool run;
int type;
int count;
Word chksum;
Word addr;
Byte b;
 
printf("Trying to connect to load server...\n");
for (i = 0; i < NUM_TRIES; i++) {
serialOut(serno, SYN);
for (j = 0; j < WAIT_DELAY; j++) {
if (serialChk(serno) != 0) {
break;
}
}
if (j < WAIT_DELAY) {
break;
}
printf("Request timed out...\n");
}
if (i == NUM_TRIES ||
serialIn(serno) != ACK) {
printf("Unable to establish connection to load server.\n");
return;
}
serialOut(serno, ACK);
printf("Connected to load server.\n");
run = true;
while (run) {
serialOut(serno, 'r');
for (i = 0; i < LINE_SIZE; i++) {
line[i] = serialIn(serno);
if (line[i] == '\n') {
break;
}
}
if (i == LINE_SIZE) {
printf("Error: too many characters in S-record!\n");
break;
}
line[i] = '\0';
printf("%s\n", line);
if (line[0] != 'S') {
printf("Error: malformed S-record!\n");
break;
}
type = line[1];
count = getByte(2);
if (i != 2 * count + 4) {
printf("Error: inconsistent byte count in S-record!\n");
break;
}
chksum = 0;
for (j = 2; j < i; j += 2) {
chksum += getByte(j);
}
if ((chksum & 0xFF) != 0xFF) {
printf("Error: wrong checksum in S-record!\n");
break;
}
switch (type) {
case '0':
/* S0 record: header (skip) */
break;
case '1':
/* S1 record: 2 byte load address + data (load data) */
addr = (getByte( 4) << 8) |
(getByte( 6) << 0);
addr |= 0xC0000000;
for (j = 0; j < count - 3; j++) {
b = getByte(2 * j + 8);
mmuWriteByte(addr + j, b);
}
break;
case '2':
/* S2 record: 3 byte load address + data (load data) */
addr = (getByte( 4) << 16) |
(getByte( 6) << 8) |
(getByte( 8) << 0);
addr |= 0xC0000000;
for (j = 0; j < count - 4; j++) {
b = getByte(2 * j + 10);
mmuWriteByte(addr + j, b);
}
break;
case '3':
/* S3 record: 4 byte load address + data (load data) */
addr = (getByte( 4) << 24) |
(getByte( 6) << 16) |
(getByte( 8) << 8) |
(getByte(10) << 0);
addr |= 0xC0000000;
for (j = 0; j < count - 5; j++) {
b = getByte(2 * j + 12);
mmuWriteByte(addr + j, b);
}
break;
case '5':
/* S5 record: record count (skip) */
break;
case '7':
/* S7 record: 4 byte start address (set PC, stop loading) */
addr = (getByte( 4) << 24) |
(getByte( 6) << 16) |
(getByte( 8) << 8) |
(getByte(10) << 0);
addr |= 0xC0000000;
cpuSetPC(addr);
run = false;
break;
case '8':
/* S8 record: 3 byte start address (set PC, stop loading) */
addr = (getByte( 4) << 16) |
(getByte( 6) << 8) |
(getByte( 8) << 0);
addr |= 0xC0000000;
cpuSetPC(addr);
run = false;
break;
case '9':
/* S9 record: 2 byte start address (set PC, stop loading) */
addr = (getByte( 4) << 8) |
(getByte( 6) << 0);
addr |= 0xC0000000;
cpuSetPC(addr);
run = false;
break;
default:
/* unknown type of S-record */
printf("Error: unknown type of S-record!\n");
run = false;
break;
}
}
serialOut(serno, 'q');
printf("Connection to load server closed.\n");
if (start) {
cpuRun();
}
}
/common/load.h
0,0 → 1,13
/*
* load.h -- load S-records from serial line
*/
 
 
#ifndef _LOAD_H_
#define _LOAD_H_
 
 
void load(int serno, Bool start);
 
 
#endif /* _LOAD_H_ */
/common/main.c
0,0 → 1,32
/*
* main.c -- the main program
*/
 
 
#include "common.h"
#include "stdarg.h"
#include "romlib.h"
#include "command.h"
#include "getline.h"
#include "instr.h"
#include "cpu.h"
 
 
#define VERSION "1.06"
#define PROMPT "ECO32 > "
 
 
int main(void) {
char *line;
 
printf("\n\nECO32 Machine Monitor %s\n\n", VERSION);
initInstrTable();
cpuSetPC(0xC0010000);
cpuSetPSW(0x08000000);
while (1) {
line = getLine(PROMPT);
addHist(line);
execCommand(line);
}
return 0;
}
/common/boot.c
0,0 → 1,48
/*
* boot.c -- bootstrap from disk
*/
 
 
#include "common.h"
#include "stdarg.h"
#include "romlib.h"
#include "boot.h"
#include "cpu.h"
#include "mmu.h"
#include "start.h"
 
 
void boot(int dskno, Bool start) {
Word capacity;
Byte sig1, sig2;
 
capacity = dskcap(dskno);
if (capacity == 0) {
printf("Disk not found!\n");
return;
}
printf("Disk with 0x%08X sectors found, booting...\n", capacity);
if (dskio(dskno, 'r', 0, PHYS_BOOT, 1) != 0) {
printf("Disk error!\n");
return;
}
sig1 = mmuReadByte(VIRT_BOOT + 512 - 2);
sig2 = mmuReadByte(VIRT_BOOT + 512 - 1);
if (sig1 != 0x55 || sig2 != 0xAA) {
printf("MBR signature missing!\n");
return;
}
/*
* Boot convention:
* $16 disk number of boot disk
* $17 start sector number of disk or partition to boot
* $18 total number of sectors of disk or partition to boot
*/
cpuSetReg(16, dskno);
cpuSetReg(17, 0);
cpuSetReg(18, capacity);
cpuSetPC(VIRT_BOOT);
if (start) {
cpuRun();
}
}
/common/boot.h
0,0 → 1,17
/*
* boot.h -- bootstrap from disk
*/
 
 
#ifndef _BOOT_H_
#define _BOOT_H_
 
 
#define PHYS_BOOT 0x00010000 /* where to load the bootstrap */
#define VIRT_BOOT 0xC0010000 /* where to start the bootstrap */
 
 
void boot(int dskno, Bool start);
 
 
#endif /* _BOOT_H_ */
/common/cpu.c
0,0 → 1,365
/*
* cpu.c -- execute instructions
*/
 
 
#include "common.h"
#include "stdarg.h"
#include "romlib.h"
#include "instr.h"
#include "cpu.h"
#include "mmu.h"
#include "start.h"
 
 
#define RR(n) r[n]
#define WR(n,d) ((void) ((n) != 0 ? r[n] = (d) : (d)))
 
#define BREAK ((OP_TRAP << 26) | 0x0001)
 
 
/**************************************************************/
 
 
static Word pc; /* program counter */
static Word psw; /* processor status word */
static Word r[32]; /* general purpose registers */
 
static Bool breakSet; /* breakpoint set if true */
static Word breakAddr; /* if breakSet, this is where */
 
 
/**************************************************************/
 
 
Word cpuGetPC(void) {
return pc;
}
 
 
void cpuSetPC(Word addr) {
pc = addr;
}
 
 
Word cpuGetReg(int regnum) {
return RR(regnum & 0x1F);
}
 
 
void cpuSetReg(int regnum, Word value) {
WR(regnum & 0x1F, value);
}
 
 
Word cpuGetPSW(void) {
return psw;
}
 
 
void cpuSetPSW(Word value) {
psw = value;
}
 
 
Bool cpuTestBreak(void) {
return breakSet;
}
 
 
Word cpuGetBreak(void) {
return breakAddr;
}
 
 
void cpuSetBreak(Word addr) {
breakAddr = addr;
breakSet = true;
}
 
 
void cpuResetBreak(void) {
breakSet = false;
}
 
 
/**************************************************************/
 
 
static char *cause[32] = {
/* 0 */ "serial line 0 xmt interrupt",
/* 1 */ "serial line 0 rcv interrupt",
/* 2 */ "serial line 1 xmt interrupt",
/* 3 */ "serial line 1 rcv interrupt",
/* 4 */ "keyboard interrupt",
/* 5 */ "unknown interrupt",
/* 6 */ "unknown interrupt",
/* 7 */ "unknown interrupt",
/* 8 */ "disk interrupt",
/* 9 */ "unknown interrupt",
/* 10 */ "unknown interrupt",
/* 11 */ "unknown interrupt",
/* 12 */ "unknown interrupt",
/* 13 */ "unknown interrupt",
/* 14 */ "timer 0 interrupt",
/* 15 */ "timer 1 interrupt",
/* 16 */ "bus timeout exception",
/* 17 */ "illegal instruction exception",
/* 18 */ "privileged instruction exception",
/* 19 */ "divide instruction exception",
/* 20 */ "trap instruction exception",
/* 21 */ "TLB miss exception",
/* 22 */ "TLB write exception",
/* 23 */ "TLB invalid exception",
/* 24 */ "illegal address exception",
/* 25 */ "privileged address exception",
/* 26 */ "unknown exception",
/* 27 */ "unknown exception",
/* 28 */ "unknown exception",
/* 29 */ "unknown exception",
/* 30 */ "unknown exception",
/* 31 */ "unknown exception"
};
 
 
char *exceptionToString(int exception) {
if (exception < 0 ||
exception >= sizeof(cause)/sizeof(cause[0])) {
return "<exception number out of bounds>";
}
return cause[exception];
}
 
 
/**************************************************************/
 
 
static Byte stepType[64] = {
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
/* 0x00 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/* 0x10 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/* 0x20 */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 4, 3, 4, 1, 0,
/* 0x30 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
};
 
 
static Bool evalCond(int cc, Word a, Word b) {
switch (cc) {
case 0:
/* equal */
if (a == b) {
return true;
}
break;
case 1:
/* not equal */
if (a != b) {
return true;
}
break;
case 2:
/* less or equal (signed) */
if ((signed int) a <= (signed int) b) {
return true;
}
break;
case 3:
/* less or equal (unsigned) */
if (a <= b) {
return true;
}
break;
case 4:
/* less than (signed) */
if ((signed int) a < (signed int) b) {
return true;
}
break;
case 5:
/* less than (unsigned) */
if (a < b) {
return true;
}
break;
case 6:
/* greater or equal (signed) */
if ((signed int) a >= (signed int) b) {
return true;
}
break;
case 7:
/* greater or equal (unsigned) */
if (a >= b) {
return true;
}
break;
case 8:
/* greater than (signed) */
if ((signed int) a > (signed int) b) {
return true;
}
break;
case 9:
/* greater than (unsigned) */
if (a > b) {
return true;
}
break;
default:
/* this should never happen */
printf("cannot compute condition code %d\n", cc);
break;
}
return false;
}
 
 
void cpuStep(void) {
Word instr;
int opcode;
int reg1, reg2;
Half immed;
Word offset;
Word nextAddr;
Word nextInstr;
int i;
MonitorState stepState;
MonitorState *origReturn;
 
instr = mmuReadWord(pc);
opcode = (instr >> 26) & 0x3F;
reg1 = (instr >> 21) & 0x1F;
reg2 = (instr >> 16) & 0x1F;
immed = instr & 0x0000FFFF;
offset = instr & 0x03FFFFFF;
switch (stepType[opcode]) {
case 1:
/* next instruction follows current one immediately */
nextAddr = pc + 4;
break;
case 2:
/* next instruction conditionally reached by PC relative branch */
nextAddr = pc + 4;
if (evalCond(opcode - OP_BEQ, RR(reg1), RR(reg2))) {
nextAddr += SEXT16(immed) << 2;
}
break;
case 3:
/* next instruction reached by PC relative jump */
nextAddr = pc + 4 + (SEXT26(offset) << 2);
break;
case 4:
/* next instruction reached by jump to register contents */
nextAddr = RR(reg1) & 0xFFFFFFFC;
break;
default:
printf("cannot single-step instruction with opcode 0x%02X\n",
opcode);
return;
}
nextInstr = mmuReadWord(nextAddr);
mmuWriteWord(nextAddr, BREAK);
for (i = 0; i < 32; i++) {
userContext.reg[i] = RR(i);
}
userContext.reg[30] = pc;
userContext.psw = psw;
userContext.tlbIndex = mmuGetIndex();
userContext.tlbHi = mmuGetEntryHi();
userContext.tlbLo = mmuGetEntryLo();
userContext.badAddr = mmuGetBadAddr();
userContext.badAccs = mmuGetBadAccs();
if (saveState(&stepState)) {
origReturn = monitorReturn;
monitorReturn = &stepState;
resume();
}
monitorReturn = origReturn;
for (i = 0; i < 32; i++) {
WR(i, userContext.reg[i]);
}
pc = userContext.reg[30];
psw = userContext.psw;
mmuSetIndex(userContext.tlbIndex);
mmuSetEntryHi(userContext.tlbHi);
mmuSetEntryLo(userContext.tlbLo);
mmuSetBadAddr(userContext.badAddr);
mmuSetBadAccs(userContext.badAccs);
mmuWriteWord(nextAddr, nextInstr);
if (nextAddr == pc) {
return;
}
if ((psw & PSW_PRIO_MASK) >> 16 == 21 &&
(mmuGetEntryHi() & 0x80000000) == 0) {
/* TLB user miss */
printf("unexpected TLB user miss exception occurred\n");
return;
} else {
/* any other exception */
printf("unexpected %s occurred\n",
exceptionToString((psw & PSW_PRIO_MASK) >> 16));
return;
}
}
 
 
void cpuRun(void) {
Word instr;
int i;
MonitorState runState;
MonitorState *origReturn;
 
if (breakSet && breakAddr == pc) {
/* single-step one instruction */
cpuStep();
}
while (1) {
if (breakSet) {
instr = mmuReadWord(breakAddr);
mmuWriteWord(breakAddr, BREAK);
}
for (i = 0; i < 32; i++) {
userContext.reg[i] = RR(i);
}
userContext.reg[30] = pc;
userContext.psw = psw;
userContext.tlbIndex = mmuGetIndex();
userContext.tlbHi = mmuGetEntryHi();
userContext.tlbLo = mmuGetEntryLo();
userContext.badAddr = mmuGetBadAddr();
userContext.badAccs = mmuGetBadAccs();
if (saveState(&runState)) {
origReturn = monitorReturn;
monitorReturn = &runState;
resume();
}
monitorReturn = origReturn;
for (i = 0; i < 32; i++) {
WR(i, userContext.reg[i]);
}
pc = userContext.reg[30];
psw = userContext.psw;
mmuSetIndex(userContext.tlbIndex);
mmuSetEntryHi(userContext.tlbHi);
mmuSetEntryLo(userContext.tlbLo);
mmuSetBadAddr(userContext.badAddr);
mmuSetBadAccs(userContext.badAccs);
if (breakSet) {
mmuWriteWord(breakAddr, instr);
}
if (breakSet && breakAddr == pc) {
return;
}
if ((psw & PSW_PRIO_MASK) >> 16 == 21 &&
(mmuGetEntryHi() & 0x80000000) == 0) {
/* TLB user miss */
printf("unexpected TLB user miss exception occurred\n");
return;
} else {
/* any other exception */
printf("unexpected %s occurred\n",
exceptionToString((psw & PSW_PRIO_MASK) >> 16));
return;
}
}
}
/common/start.h
0,0 → 1,55
/*
* start.h -- ECO32 ROM monitor startup and support routines
*/
 
 
#ifndef _START_H_
#define _START_H_
 
 
typedef struct {
Word reg[32]; /* general purpose registers */
Word psw; /* PSW */
Word tlbIndex; /* TLB index register */
Word tlbHi; /* TLB EntryHi register */
Word tlbLo; /* TLB EntryLo register */
Word badAddr; /* bad address register */
Word badAccs; /* bad access register */
} UserContext;
 
typedef struct {
Word r31; /* return address */
Word r29; /* stack pointer */
Word r16; /* local variable */
Word r17; /* local variable */
Word r18; /* local variable */
Word r19; /* local variable */
Word r20; /* local variable */
Word r21; /* local variable */
Word r22; /* local variable */
Word r23; /* local variable */
} MonitorState;
 
 
void setcon(Byte ctl);
int cinchk(void);
char cin(void);
int coutchk(void);
void cout(char c);
 
int dskcap(int dskno);
int dskio(int dskno, char cmd, int sct, Word addr, int nscts);
 
Word getTLB_HI(int index);
Word getTLB_LO(int index);
void setTLB(int index, Word entryHi, Word entryLo);
 
Bool saveState(MonitorState *msp);
 
extern MonitorState *monitorReturn;
extern UserContext userContext;
 
void resume(void);
 
 
#endif /* _START_H_ */
/common/dskctl.s
0,0 → 1,137
;
; dskctl.s -- disk made available by disk controller
;
 
;***************************************************************
 
.set dskbase,0xF0400000 ; disk base address
.set dskctrl,0 ; control register
.set dskcnt,4 ; count register
.set dsksct,8 ; sector register
.set dskcap,12 ; capacity register
.set dskbuf,0x00080000 ; disk buffer
 
.set ctrlstrt,0x01 ; start bit
.set ctrlien,0x02 ; interrupt enable bit
.set ctrlwrt,0x04 ; write bit
.set ctrlerr,0x08 ; error bit
.set ctrldone,0x10 ; done bit
.set ctrlrdy,0x20 ; ready bit
 
.set sctsize,512 ; sector size in bytes
 
.set retries,1000000 ; retries to get disk ready
 
.export dskinitctl ; initialize disk
.export dskcapctl ; determine disk capacity
.export dskioctl ; do disk I/O
 
;***************************************************************
 
.code
.align 4
 
dskinitctl:
jr $31
 
dskcapctl:
add $8,$0,retries ; set retry count
add $9,$0,dskbase
dskcap1:
ldw $10,$9,dskctrl
and $10,$10,ctrlrdy ; ready?
bne $10,$0,dskcapok ; yes - jump
sub $8,$8,1
bne $8,$0,dskcap1 ; try again
add $2,$0,0 ; no disk found
j dskcapx
dskcapok:
ldw $2,$9,dskcap ; get disk capacity
dskcapx:
jr $31
 
dskioctl:
sub $29,$29,24
stw $31,$29,20
stw $16,$29,16
stw $17,$29,12
stw $18,$29,8
stw $19,$29,4
stw $20,$29,0
add $16,$4,$0 ; command
add $17,$5,$0 ; sector number
add $18,$6,0xC0000000 ; memory address, virtualized
add $19,$7,$0 ; number of sectors
 
add $8,$0,'r'
beq $16,$8,dskrd
add $8,$0,'w'
beq $16,$8,dskwr
add $2,$0,0xFF ; illegal command
j dskx
 
dskrd:
add $2,$0,$0 ; return ok
beq $19,$0,dskx ; if no (more) sectors
add $8,$0,dskbase
add $9,$0,1
stw $9,$8,dskcnt ; number of sectors
stw $17,$8,dsksct ; sector number on disk
add $9,$0,ctrlstrt
stw $9,$8,dskctrl ; start command
dskrd1:
ldw $2,$8,dskctrl
and $9,$2,ctrldone ; done?
beq $9,$0,dskrd1 ; no - wait
and $9,$2,ctrlerr ; error?
bne $9,$0,dskx ; yes - leave
add $8,$0,dskbase + dskbuf ; transfer data
add $9,$0,sctsize
dskrd2:
ldw $10,$8,0 ; from disk buffer
stw $10,$18,0 ; to memory
add $8,$8,4
add $18,$18,4
sub $9,$9,4
bne $9,$0,dskrd2
add $17,$17,1 ; increment sector number
sub $19,$19,1 ; decrement number of sectors
j dskrd ; next sector
 
dskwr:
add $2,$0,$0 ; return ok
beq $19,$0,dskx ; if no (more) sectors
add $8,$0,dskbase + dskbuf ; transfer data
add $9,$0,sctsize
dskwr1:
ldw $10,$18,0 ; from memory
stw $10,$8,0 ; to disk buffer
add $18,$18,4
add $8,$8,4
sub $9,$9,4
bne $9,$0,dskwr1
add $8,$0,dskbase
add $9,$0,1
stw $9,$8,dskcnt ; number of sectors
stw $17,$8,dsksct ; sector number on disk
add $9,$0,ctrlwrt | ctrlstrt
stw $9,$8,dskctrl ; start command
dskwr2:
ldw $2,$8,dskctrl
and $9,$2,ctrldone ; done?
beq $9,$0,dskwr2 ; no - wait
and $9,$2,ctrlerr ; error?
bne $9,$0,dskx ; yes - leave
add $17,$17,1 ; increment sector number
sub $19,$19,1 ; decrement number of sectors
j dskwr ; next sector
 
dskx:
ldw $20,$29,0
ldw $19,$29,4
ldw $18,$29,8
ldw $17,$29,12
ldw $16,$29,16
ldw $31,$29,20
add $29,$29,24
jr $31
/common/dskser.s
0,0 → 1,204
;
; dskser.s -- disk made available by serial interface
;
 
;***************************************************************
 
.export dskinitser ; initialize disk
.export dskcapser ; determine disk capacity
.export dskioser ; do disk I/O
 
.import ser1in
.import ser1out
.import ser1inchk
.import puts
 
; constants for communication with disk server
.set SYN,0x16 ; to initiate the three-way handshake
.set ACK,0x06 ; acknowledgement for handshake
.set RESULT_OK,0x00 ; server successfully executed cmd
; everything else means error
 
.set WAIT_DELAY,800000 ; count for delay loop
 
;***************************************************************
 
.code
.align 4
 
dskinitser:
jr $31
 
dskcapser:
sub $29,$29,16
stw $16,$29,0
stw $17,$29,4
stw $18,$29,8
stw $31,$29,12
add $4,$0,trymsg ; say what we are doing
jal puts
add $18,$0,$0 ; capacity == 0 if disk not present
add $16,$0,10 ; 10 tries to get a connection
handshake1:
sub $16,$16,1
add $4,$0,SYN
jal ser1out ; send SYN
add $17,$0,WAIT_DELAY ; wait for ACK
handshake2:
sub $17,$17,1
jal ser1inchk
bne $2,$0,handshake3
bne $17,$0,handshake2
add $4,$0,timeoutmsg
jal puts
bne $16,$0,handshake1
add $4,$0,frustratedmsg
jal puts
j dskcapx
handshake3:
jal ser1in
add $8,$0,ACK
bne $2,$8,dskcapx
; we got an ACK so we return it
add $4,$0,ACK
jal ser1out
 
; ask it for its capacity
add $4,$0,'c'
jal ser1out ; request
jal ser1in ; first byte of response
bne $2,$0,dskcapx ; exit if error
 
; all is well and the server will give us the capacity
add $16,$0,4 ; 4 bytes to read
dskcap1:
sll $18,$18,8
jal ser1in
or $18,$18,$2 ; most significant byte first
sub $16,$16,1
bne $16,$0,dskcap1
 
; return value is in $18
dskcapx:
add $2,$0,$18
ldw $16,$29,0
ldw $17,$29,4
ldw $18,$29,8
ldw $31,$29,12
add $29,$29,16
jr $31
 
.data
.align 4
 
trymsg:
.byte "Trying to connect to disk server..."
.byte 0x0A, 0
 
timeoutmsg:
.byte "Request timed out..."
.byte 0x0A, 0
 
frustratedmsg:
.byte "Unable to establish connection to disk server."
.byte 0x0A, 0
 
.code
.align 4
 
dskioser:
sub $29,$29,24
stw $16,$29,0
stw $17,$29,4
stw $18,$29,8
stw $19,$29,12
stw $20,$29,16
stw $31,$29,20
add $16,$0,$4 ; command
add $17,$0,$5 ; start at sector
add $8,$0,0xc0000000
or $18,$8,$6 ; memory address (logicalized)
add $19,$0,$7 ; number of sectors
 
; switch over command
add $8,$0,'r'
beq $8,$16,dskior ; read
add $8,$0,'w'
beq $8,$16,dskiow ; write
; unknown command
add $2,$0,1 ; value != 0 signifies error
j dskiox
 
; read from disk
dskior:
dskior1: ; loop over number of sectors
beq $19,$0,dskiorsuc ; successful return
sub $19,$19,1
; read a sector
add $4,$0,'r'
jal ser1out
; send sector number
add $20,$0,32 ; 4 bytes
dskior2:
sub $20,$20,8
slr $4,$17,$20
and $4,$4,0xff
jal ser1out
bne $20,$0,dskior2
add $17,$17,1
; get answer
jal ser1in
bne $2,$0,dskiox ; $2 != 0 so we use it as return code
; read data
add $20,$0,512
dskior3:
sub $20,$20,1
jal ser1in
stb $2,$18,0
add $18,$18,1
bne $20,$0,dskior3
j dskior1
dskiorsuc:
add $2,$0,$0
j dskiox
 
; write to disk
dskiow:
dskiow1: ; loop over number of sectors
beq $19,$0,dskiowsuc ; successful return
sub $19,$19,1
; write a sector
add $4,$0,'w'
jal ser1out
; send sector number
add $20,$0,32 ; 4 bytes
dskiow2:
sub $20,$20,8
slr $4,$17,$20
and $4,$4,0xff
jal ser1out
bne $20,$0,dskiow2
add $17,$17,1
; write data
add $20,$0,512
dskiow3:
sub $20,$20,1
ldbu $4,$18,0
jal ser1out
add $18,$18,1
bne $20,$0,dskiow3
; get answer
jal ser1in
bne $2,$0,dskiox
j dskiow1
dskiowsuc:
add $2,$0,$0
dskiox:
ldw $16,$29,0
ldw $17,$29,4
ldw $18,$29,8
ldw $19,$29,12
ldw $20,$29,16
ldw $31,$29,20
add $29,$29,24
jr $31
/common/serial.s
0,0 → 1,96
;
; serial.s -- the serial line interface
;
 
;***************************************************************
 
.set ser0base,0xF0300000 ; serial line 0 base address
.set ser1base,0xF0301000 ; serial line 1 base address
 
.export ser0init ; line 0 initialization
.export ser0inchk ; line 0 input check
.export ser0in ; line 0 input
.export ser0outchk ; line 0 output check
.export ser0out ; line 0 output
 
.export ser1init ; line 1 initialization
.export ser1inchk ; line 1 input check
.export ser1in ; line 1 input
.export ser1outchk ; line 1 output check
.export ser1out ; line 1 output
 
;***************************************************************
 
.code
.align 4
 
ser0init:
jr $31
 
ser0inchk:
add $8,$0,ser0base
ldw $2,$8,0
and $2,$2,1
jr $31
 
ser0in:
add $8,$0,ser0base
ser0in1:
ldw $9,$8,0
and $9,$9,1
beq $9,$0,ser0in1
ldw $2,$8,4
jr $31
 
ser0outchk:
add $8,$0,ser0base
ldw $2,$8,8
and $2,$2,1
jr $31
 
ser0out:
add $8,$0,ser0base
ser0out1:
ldw $9,$8,8
and $9,$9,1
beq $9,$0,ser0out1
stw $4,$8,12
jr $31
 
;***************************************************************
 
.code
.align 4
 
ser1init:
jr $31
 
ser1inchk:
add $8,$0,ser1base
ldw $2,$8,0
and $2,$2,1
jr $31
 
ser1in:
add $8,$0,ser1base
ser1in1:
ldw $9,$8,0
and $9,$9,1
beq $9,$0,ser1in1
ldw $2,$8,4
jr $31
 
ser1outchk:
add $8,$0,ser1base
ldw $2,$8,8
and $2,$2,1
jr $31
 
ser1out:
add $8,$0,ser1base
ser1out1:
ldw $9,$8,8
and $9,$9,1
beq $9,$0,ser1out1
stw $4,$8,12
jr $31
/common/serial.h
0,0 → 1,23
/*
* serial.s -- the serial line interface
*/
 
 
#ifndef _SERIAL_H_
#define _SERIAL_H_
 
 
void ser0init(void);
int ser0inchk(void);
int ser0in(void);
int ser0outchk(void);
void ser0out(int c);
 
void ser1init(void);
int ser1inchk(void);
int ser1in(void);
int ser1outchk(void);
void ser1out(int c);
 
 
#endif /* _SERIAL_H_ */
/common/mmu.c
0,0 → 1,126
/*
* mmu.c -- memory and TLB access
*/
 
 
#include "common.h"
#include "stdarg.h"
#include "romlib.h"
#include "mmu.h"
#include "start.h"
 
 
static Word tlbIndex;
static Word tlbEntryHi;
static Word tlbEntryLo;
static Word badAddress;
static Word badAccess;
 
 
Word mmuReadWord(Word vAddr) {
return *(Word *)vAddr;
}
 
 
Half mmuReadHalf(Word vAddr) {
return *(Half *)vAddr;
}
 
 
Byte mmuReadByte(Word vAddr) {
return *(Byte *)vAddr;
}
 
 
void mmuWriteWord(Word vAddr, Word data) {
*(Word *)vAddr = data;
}
 
 
void mmuWriteHalf(Word vAddr, Half data) {
*(Half *)vAddr = data;
}
 
 
void mmuWriteByte(Word vAddr, Byte data) {
*(Byte *)vAddr = data;
}
 
 
Word mmuGetIndex(void) {
return tlbIndex;
}
 
 
void mmuSetIndex(Word value) {
tlbIndex = value;
}
 
 
Word mmuGetEntryHi(void) {
return tlbEntryHi;
}
 
 
void mmuSetEntryHi(Word value) {
tlbEntryHi = value;
}
 
 
Word mmuGetEntryLo(void) {
return tlbEntryLo;
}
 
 
void mmuSetEntryLo(Word value) {
tlbEntryLo = value;
}
 
 
Word mmuGetBadAddr(void) {
return badAddress;
}
 
 
void mmuSetBadAddr(Word value) {
badAddress = value;
}
 
 
Word mmuGetBadAccs(void) {
return badAccess;
}
 
 
void mmuSetBadAccs(Word value) {
badAccess = value;
}
 
 
TLB_Entry mmuGetTLB(int index) {
Word hi;
Word lo;
TLB_Entry result;
 
hi = getTLB_HI(index);
lo = getTLB_LO(index);
result.page = hi & PAGE_MASK;
result.frame = lo & PAGE_MASK;
result.write = (lo & TLB_WRITE) ? true : false;
result.valid = (lo & TLB_VALID) ? true : false;
return result;
}
 
 
void mmuSetTLB(int index, TLB_Entry tlbEntry) {
Word flags;
 
flags = 0;
if (tlbEntry.write) {
flags |= TLB_WRITE;
}
if (tlbEntry.valid) {
flags |= TLB_VALID;
}
setTLB(index, tlbEntry.page, tlbEntry.frame | flags);
}
/common/mmu.h
0,0 → 1,56
/*
* mmu.h -- memory and TLB access
*/
 
 
#ifndef _MMU_H_
#define _MMU_H_
 
 
#define TLB_SHFT 5 /* log2 of number of TLB entries */
#define TLB_SIZE (1 << TLB_SHFT) /* total number of TLB entries */
#define TLB_MASK (TLB_SIZE - 1) /* mask for number of TLB entries */
#define TLB_FIXED 4 /* number of fixed TLB entries */
 
#define TLB_WRITE (1 << 1) /* write bit in EntryLo */
#define TLB_VALID (1 << 0) /* valid bit in EntryLo */
 
#define MMU_ACCS_MASK 0x07 /* bits used in BadAccs */
#define MMU_ACCS_READ 0x00 /* access type = read */
#define MMU_ACCS_WRITE 0x04 /* access type = write */
#define MMU_ACCS_BYTE 0x00 /* access width = byte */
#define MMU_ACCS_HALF 0x01 /* access width = half */
#define MMU_ACCS_WORD 0x02 /* access width = word */
 
 
typedef struct {
Word page; /* 20 high-order bits of virtual address */
Word frame; /* 20 high-order bits of physical address */
Bool write; /* must be true to allow writing to the page */
Bool valid; /* must be true for the entry to be valid */
} TLB_Entry;
 
 
Word mmuReadWord(Word vAddr);
Half mmuReadHalf(Word vAddr);
Byte mmuReadByte(Word vAddr);
void mmuWriteWord(Word vAddr, Word data);
void mmuWriteHalf(Word vAddr, Half data);
void mmuWriteByte(Word vAddr, Byte data);
 
Word mmuGetIndex(void);
void mmuSetIndex(Word value);
Word mmuGetEntryHi(void);
void mmuSetEntryHi(Word value);
Word mmuGetEntryLo(void);
void mmuSetEntryLo(Word value);
Word mmuGetBadAddr(void);
void mmuSetBadAddr(Word value);
Word mmuGetBadAccs(void);
void mmuSetBadAccs(Word value);
 
TLB_Entry mmuGetTLB(int index);
void mmuSetTLB(int index, TLB_Entry tlbEntry);
 
 
#endif /* _MMU_H_ */
/common/instr.c
0,0 → 1,115
/*
* instr.c -- instruction encoding
*/
 
 
#include "common.h"
#include "stdarg.h"
#include "romlib.h"
#include "instr.h"
 
 
/*
* This is the ECO32 machine instruction set.
* The table below needs no particular order
* and may have gaps in the instruction encoding.
*/
Instr instrTbl[] = {
{ "add", FORMAT_RRY, OP_ADD },
{ "sub", FORMAT_RRY, OP_SUB },
{ "mul", FORMAT_RRY, OP_MUL },
{ "mulu", FORMAT_RRX, OP_MULU },
{ "div", FORMAT_RRY, OP_DIV },
{ "divu", FORMAT_RRX, OP_DIVU },
{ "rem", FORMAT_RRY, OP_REM },
{ "remu", FORMAT_RRX, OP_REMU },
{ "and", FORMAT_RRX, OP_AND },
{ "or", FORMAT_RRX, OP_OR },
{ "xor", FORMAT_RRX, OP_XOR },
{ "xnor", FORMAT_RRX, OP_XNOR },
{ "sll", FORMAT_RRX, OP_SLL },
{ "slr", FORMAT_RRX, OP_SLR },
{ "sar", FORMAT_RRX, OP_SAR },
{ "ldhi", FORMAT_RHH, OP_LDHI },
{ "beq", FORMAT_RRB, OP_BEQ },
{ "bne", FORMAT_RRB, OP_BNE },
{ "ble", FORMAT_RRB, OP_BLE },
{ "bleu", FORMAT_RRB, OP_BLEU },
{ "blt", FORMAT_RRB, OP_BLT },
{ "bltu", FORMAT_RRB, OP_BLTU },
{ "bge", FORMAT_RRB, OP_BGE },
{ "bgeu", FORMAT_RRB, OP_BGEU },
{ "bgt", FORMAT_RRB, OP_BGT },
{ "bgtu", FORMAT_RRB, OP_BGTU },
{ "j", FORMAT_J, OP_J },
{ "jr", FORMAT_JR, OP_JR },
{ "jal", FORMAT_J, OP_JAL },
{ "jalr", FORMAT_JR, OP_JALR },
{ "trap", FORMAT_N, OP_TRAP },
{ "rfx", FORMAT_N, OP_RFX },
{ "ldw", FORMAT_RRS, OP_LDW },
{ "ldh", FORMAT_RRS, OP_LDH },
{ "ldhu", FORMAT_RRS, OP_LDHU },
{ "ldb", FORMAT_RRS, OP_LDB },
{ "ldbu", FORMAT_RRS, OP_LDBU },
{ "stw", FORMAT_RRS, OP_STW },
{ "sth", FORMAT_RRS, OP_STH },
{ "stb", FORMAT_RRS, OP_STB },
{ "mvfs", FORMAT_RH, OP_MVFS },
{ "mvts", FORMAT_RH, OP_MVTS },
{ "tbs", FORMAT_N, OP_TBS },
{ "tbwr", FORMAT_N, OP_TBWR },
{ "tbri", FORMAT_N, OP_TBRI },
{ "tbwi", FORMAT_N, OP_TBWI }
};
 
 
Instr *instrCodeTbl[64];
 
 
static int instrCompare(const void *instr1, const void *instr2) {
return strcmp(((Instr *) instr1)->name, ((Instr *) instr2)->name);
}
 
 
void initInstrTable(void) {
int i;
 
/* first sort instruction table alphabetically */
qsort(instrTbl, sizeof(instrTbl)/sizeof(instrTbl[0]),
sizeof(instrTbl[0]), instrCompare);
/* then initialize instruction code table */
for (i = 0; i < 64; i++) {
instrCodeTbl[i] = NULL;
}
for (i = 0; i < sizeof(instrTbl)/sizeof(instrTbl[0]); i++) {
instrCodeTbl[instrTbl[i].opcode] = &instrTbl[i];
if (instrTbl[i].format == FORMAT_RRX ||
instrTbl[i].format == FORMAT_RRY) {
/* enter the immediate variant of this instruction also */
instrCodeTbl[instrTbl[i].opcode + 1] = &instrTbl[i];
}
}
}
 
 
Instr *lookupInstr(char *name) {
int lo, hi, tst;
int res;
 
lo = 0;
hi = sizeof(instrTbl) / sizeof(instrTbl[0]) - 1;
while (lo <= hi) {
tst = (lo + hi) / 2;
res = strcmp(instrTbl[tst].name, name);
if (res == 0) {
return &instrTbl[tst];
}
if (res < 0) {
lo = tst + 1;
} else {
hi = tst - 1;
}
}
return NULL;
}
/common/instr.h
0,0 → 1,125
/*
* instr.h -- instruction encoding
*/
 
 
#ifndef _INSTR_H_
#define _INSTR_H_
 
 
#define FORMAT_N 0 /* no operands */
#define FORMAT_RH 1 /* one register and a half operand */
#define FORMAT_RHH 2 /* one register and a half operand */
/* ATTENTION: high-order 16 bits encoded */
#define FORMAT_RRH 3 /* two registers and a half operand */
#define FORMAT_RRS 4 /* two registers and a signed half operand */
#define FORMAT_RRR 5 /* three register operands */
#define FORMAT_RRX 6 /* either FORMAT_RRR or FORMAT_RRH */
#define FORMAT_RRY 7 /* either FORMAT_RRR or FORMAT_RRS */
#define FORMAT_RRB 8 /* two registers and a 16 bit signed
offset operand */
#define FORMAT_J 9 /* no registers and a 26 bit signed
offset operand */
#define FORMAT_JR 10 /* one register operand */
 
 
#define MASK(n) ((((Word) 1) << n) - 1)
#define SIGN(n) (((Word) 1) << (n - 1))
#define ZEXT16(x) (((Word) (x)) & MASK(16))
#define SEXT16(x) (((Word) (x)) & SIGN(16) ? \
(((Word) (x)) | ~MASK(16)) : \
(((Word) (x)) & MASK(16)))
#define SEXT26(x) (((Word) (x)) & SIGN(26) ? \
(((Word) (x)) | ~MASK(26)) : \
(((Word) (x)) & MASK(26)))
 
 
#define OP_ADD 0x00
#define OP_ADDI 0x01
#define OP_SUB 0x02
#define OP_SUBI 0x03
 
#define OP_MUL 0x04
#define OP_MULI 0x05
#define OP_MULU 0x06
#define OP_MULUI 0x07
#define OP_DIV 0x08
#define OP_DIVI 0x09
#define OP_DIVU 0x0A
#define OP_DIVUI 0x0B
#define OP_REM 0x0C
#define OP_REMI 0x0D
#define OP_REMU 0x0E
#define OP_REMUI 0x0F
 
#define OP_AND 0x10
#define OP_ANDI 0x11
#define OP_OR 0x12
#define OP_ORI 0x13
#define OP_XOR 0x14
#define OP_XORI 0x15
#define OP_XNOR 0x16
#define OP_XNORI 0x17
 
#define OP_SLL 0x18
#define OP_SLLI 0x19
#define OP_SLR 0x1A
#define OP_SLRI 0x1B
#define OP_SAR 0x1C
#define OP_SARI 0x1D
 
#define OP_LDHI 0x1F
 
#define OP_BEQ 0x20
#define OP_BNE 0x21
#define OP_BLE 0x22
#define OP_BLEU 0x23
#define OP_BLT 0x24
#define OP_BLTU 0x25
#define OP_BGE 0x26
#define OP_BGEU 0x27
#define OP_BGT 0x28
#define OP_BGTU 0x29
 
#define OP_J 0x2A
#define OP_JR 0x2B
#define OP_JAL 0x2C
#define OP_JALR 0x2D
 
#define OP_TRAP 0x2E
#define OP_RFX 0x2F
 
#define OP_LDW 0x30
#define OP_LDH 0x31
#define OP_LDHU 0x32
#define OP_LDB 0x33
#define OP_LDBU 0x34
 
#define OP_STW 0x35
#define OP_STH 0x36
#define OP_STB 0x37
 
#define OP_MVFS 0x38
#define OP_MVTS 0x39
#define OP_TBS 0x3A
#define OP_TBWR 0x3B
#define OP_TBRI 0x3C
#define OP_TBWI 0x3D
 
 
typedef struct {
char *name;
int format;
Byte opcode;
} Instr;
 
 
extern Instr instrTbl[];
extern Instr *instrCodeTbl[];
 
 
void initInstrTable(void);
Instr *lookupInstr(char *name);
 
 
#endif /* _INSTR_H_ */
/common/disasm.c
0,0 → 1,138
/*
* disasm.c -- disassembler
*/
 
 
#include "common.h"
#include "stdarg.h"
#include "romlib.h"
#include "instr.h"
#include "disasm.h"
 
 
static char instrBuffer[100];
 
 
static void disasmN(char *opName, Word immed) {
if (immed == 0) {
sprintf(instrBuffer, "%-7s", opName);
} else {
sprintf(instrBuffer, "%-7s %08X", opName, immed);
}
}
 
 
static void disasmRH(char *opName, int r1, Half immed) {
sprintf(instrBuffer, "%-7s $%d,%04X", opName, r1, immed);
}
 
 
static void disasmRHH(char *opName, int r1, Half immed) {
sprintf(instrBuffer, "%-7s $%d,%08X", opName, r1, (Word) immed << 16);
}
 
 
static void disasmRRH(char *opName, int r1, int r2, Half immed) {
sprintf(instrBuffer, "%-7s $%d,$%d,%04X", opName, r1, r2, immed);
}
 
 
static void disasmRRS(char *opName, int r1, int r2, Half immed) {
sprintf(instrBuffer, "%-7s $%d,$%d,%s%04X", opName, r1, r2,
SIGN(16) & immed ? "-" : "+",
SIGN(16) & immed ? -(signed)SEXT16(immed) : SEXT16(immed));
}
 
 
static void disasmRRR(char *opName, int r1, int r2, int r3) {
sprintf(instrBuffer, "%-7s $%d,$%d,$%d", opName, r1, r2, r3);
}
 
 
static void disasmRRB(char *opName, int r1, int r2, Half offset, Word locus) {
sprintf(instrBuffer, "%-7s $%d,$%d,%08X", opName,
r1, r2, (locus + 4) + (SEXT16(offset) << 2));
}
 
 
static void disasmJ(char *opName, Word offset, Word locus) {
sprintf(instrBuffer, "%-7s %08X", opName,
(locus + 4) + (SEXT26(offset) << 2));
}
 
 
static void disasmJR(char *opName, int r1) {
sprintf(instrBuffer, "%-7s $%d", opName, r1);
}
 
 
char *disasm(Word instr, Word locus) {
Byte opcode;
Instr *ip;
 
opcode = (instr >> 26) & 0x3F;
ip = instrCodeTbl[opcode];
if (ip == NULL) {
disasmN("???", 0);
} else {
switch (ip->format) {
case FORMAT_N:
disasmN(ip->name, instr & 0x03FFFFFF);
break;
case FORMAT_RH:
disasmRH(ip->name, (instr >> 16) & 0x1F, instr & 0x0000FFFF);
break;
case FORMAT_RHH:
disasmRHH(ip->name, (instr >> 16) & 0x1F, instr & 0x0000FFFF);
break;
case FORMAT_RRH:
disasmRRH(ip->name, (instr >> 16) & 0x1F,
(instr >> 21) & 0x1F, instr & 0x0000FFFF);
break;
case FORMAT_RRS:
disasmRRS(ip->name, (instr >> 16) & 0x1F,
(instr >> 21) & 0x1F, instr & 0x0000FFFF);
break;
case FORMAT_RRR:
disasmRRR(ip->name, (instr >> 11) & 0x1F,
(instr >> 21) & 0x1F, (instr >> 16) & 0x1F);
break;
case FORMAT_RRX:
if ((opcode & 1) == 0) {
/* the FORMAT_RRR variant */
disasmRRR(ip->name, (instr >> 11) & 0x1F,
(instr >> 21) & 0x1F, (instr >> 16) & 0x1F);
} else {
/* the FORMAT_RRH variant */
disasmRRH(ip->name, (instr >> 16) & 0x1F,
(instr >> 21) & 0x1F, instr & 0x0000FFFF);
}
break;
case FORMAT_RRY:
if ((opcode & 1) == 0) {
/* the FORMAT_RRR variant */
disasmRRR(ip->name, (instr >> 11) & 0x1F,
(instr >> 21) & 0x1F, (instr >> 16) & 0x1F);
} else {
/* the FORMAT_RRS variant */
disasmRRS(ip->name, (instr >> 16) & 0x1F,
(instr >> 21) & 0x1F, instr & 0x0000FFFF);
}
break;
case FORMAT_RRB:
disasmRRB(ip->name, (instr >> 21) & 0x1F,
(instr >> 16) & 0x1F, instr & 0x0000FFFF, locus);
break;
case FORMAT_J:
disasmJ(ip->name, instr & 0x03FFFFFF, locus);
break;
case FORMAT_JR:
disasmJR(ip->name, (instr >> 21) & 0x1F);
break;
default:
printf("illegal entry in instruction table\n");
break;
}
}
return instrBuffer;
}
/common/asm.c
0,0 → 1,370
/*
* asm.c -- assembler
*/
 
 
#include "common.h"
#include "stdarg.h"
#include "romlib.h"
#include "instr.h"
#include "asm.h"
 
 
#define MAX_TOKENS 10
 
 
static char *msgs[] = {
/* 0 */ "too many tokens on line",
/* 1 */ "empty line",
/* 2 */ "unknown instruction name",
/* 3 */ "unknown instruction format",
/* 4 */ "excess tokens on line",
/* 5 */ "too few operands",
/* 6 */ "illegal register",
/* 7 */ "illegal immediate value",
/* 8 */ "immediate value out of range",
/* 9 */ "target is not aligned",
/* 10 */ "target cannot be reached"
};
 
 
static Bool asmReg(char *token, int *reg) {
char *end;
 
if (*token != '$') {
return false;
}
*reg = strtoul(token + 1, &end, 10);
if (*end != '\0') {
return false;
}
if (*reg < 0 || *reg >= 32) {
return false;
}
return true;
}
 
 
static Bool asmNum(char *token, unsigned int *val) {
char *end;
 
*val = strtoul(token, &end, 16);
return *end == '\0';
}
 
 
char *asmInstr(char *line, Word addr, Word *instrPtr) {
char *tokens[MAX_TOKENS];
int n;
char *p;
Instr *instr;
Word result;
int r1, r2, r3;
unsigned int uimm;
signed int simm;
 
/* separate tokens */
n = 0;
p = strtok(line, " \t\n,");
while (p != NULL) {
if (n == MAX_TOKENS) {
return msgs[0];
}
tokens[n++] = p;
p = strtok(NULL, " \t\n,");
}
if (n == 0) {
return msgs[1];
}
/* lookup mnemonic */
instr = lookupInstr(tokens[0]);
if (instr == NULL) {
return msgs[2];
}
/* do processing according to format */
switch (instr->format) {
case FORMAT_N:
/* no operands (but may get a constant operand) */
if (n > 2) {
return msgs[4];
}
if (n < 1) {
return msgs[5];
}
if (n == 2) {
if (!asmNum(tokens[1], &uimm)) {
return msgs[7];
}
} else {
uimm = 0;
}
result = ((Word) instr->opcode << 26) |
(uimm & MASK(26));
break;
case FORMAT_RH:
/* one register and a half operand */
if (n > 3) {
return msgs[4];
}
if (n < 3) {
return msgs[5];
}
if (!asmReg(tokens[1], &r1)) {
return msgs[6];
}
if (!asmNum(tokens[2], &uimm)) {
return msgs[7];
}
if (uimm >= (unsigned) (1 << 16)) {
return msgs[8];
}
result = ((Word) instr->opcode << 26) |
(r1 << 16) |
(uimm & MASK(16));
break;
case FORMAT_RHH:
/* one register and a half operand */
/* ATTENTION: high-order 16 bits encoded */
if (n > 3) {
return msgs[4];
}
if (n < 3) {
return msgs[5];
}
if (!asmReg(tokens[1], &r1)) {
return msgs[6];
}
if (!asmNum(tokens[2], &uimm)) {
return msgs[7];
}
uimm >>= 16;
if (uimm >= (unsigned) (1 << 16)) {
return msgs[8];
}
result = ((Word) instr->opcode << 26) |
(r1 << 16) |
(uimm & MASK(16));
break;
case FORMAT_RRH:
/* two registers and a half operand */
if (n > 4) {
return msgs[4];
}
if (n < 4) {
return msgs[5];
}
if (!asmReg(tokens[1], &r1)) {
return msgs[6];
}
if (!asmReg(tokens[2], &r2)) {
return msgs[6];
}
if (!asmNum(tokens[3], &uimm)) {
return msgs[7];
}
if (uimm >= (unsigned) (1 << 16)) {
return msgs[8];
}
result = ((Word) instr->opcode << 26) |
(r2 << 21) |
(r1 << 16) |
(uimm & MASK(16));
break;
case FORMAT_RRS:
/* two registers and a signed half operand */
if (n > 4) {
return msgs[4];
}
if (n < 4) {
return msgs[5];
}
if (!asmReg(tokens[1], &r1)) {
return msgs[6];
}
if (!asmReg(tokens[2], &r2)) {
return msgs[6];
}
if (!asmNum(tokens[3], (unsigned int *) &simm)) {
return msgs[7];
}
if (simm >= (signed) (1 << 15) ||
simm < - (signed) (1 << 15)) {
return msgs[8];
}
result = ((Word) instr->opcode << 26) |
(r2 << 21) |
(r1 << 16) |
(simm & MASK(16));
break;
case FORMAT_RRR:
/* three register operands */
if (n > 4) {
return msgs[4];
}
if (n < 4) {
return msgs[5];
}
if (!asmReg(tokens[1], &r1)) {
return msgs[6];
}
if (!asmReg(tokens[2], &r2)) {
return msgs[6];
}
if (!asmReg(tokens[3], &r3)) {
return msgs[6];
}
result = ((Word) instr->opcode << 26) |
(r2 << 21) |
(r3 << 16) |
(r1 << 11);
break;
case FORMAT_RRX:
/* either FORMAT_RRR or FORMAT_RRH */
if (n > 4) {
return msgs[4];
}
if (n < 4) {
return msgs[5];
}
if (!asmReg(tokens[1], &r1)) {
return msgs[6];
}
if (!asmReg(tokens[2], &r2)) {
return msgs[6];
}
if (*tokens[3] == '$') {
/* FORMAT_RRR */
if (!asmReg(tokens[3], &r3)) {
return msgs[6];
}
result = ((Word) instr->opcode << 26) |
(r2 << 21) |
(r3 << 16) |
(r1 << 11);
} else {
/* FORMAT_RRH */
if (!asmNum(tokens[3], &uimm)) {
return msgs[7];
}
if (uimm >= (unsigned) (1 << 16)) {
return msgs[8];
}
result = (((Word) instr->opcode + 1) << 26) |
(r2 << 21) |
(r1 << 16) |
(uimm & MASK(16));
}
break;
case FORMAT_RRY:
/* either FORMAT_RRR or FORMAT_RRS */
if (n > 4) {
return msgs[4];
}
if (n < 4) {
return msgs[5];
}
if (!asmReg(tokens[1], &r1)) {
return msgs[6];
}
if (!asmReg(tokens[2], &r2)) {
return msgs[6];
}
if (*tokens[3] == '$') {
/* FORMAT_RRR */
if (!asmReg(tokens[3], &r3)) {
return msgs[6];
}
result = ((Word) instr->opcode << 26) |
(r2 << 21) |
(r3 << 16) |
(r1 << 11);
} else {
/* FORMAT_RRS */
if (!asmNum(tokens[3], (unsigned int *) &simm)) {
return msgs[7];
}
if (simm >= (signed) (1 << 15) ||
simm < - (signed) (1 << 15)) {
return msgs[8];
}
result = (((Word) instr->opcode + 1) << 26) |
(r2 << 21) |
(r1 << 16) |
(simm & MASK(16));
}
break;
case FORMAT_RRB:
/* two registers and a 16 bit signed offset operand */
if (n > 4) {
return msgs[4];
}
if (n < 4) {
return msgs[5];
}
if (!asmReg(tokens[1], &r1)) {
return msgs[6];
}
if (!asmReg(tokens[2], &r2)) {
return msgs[6];
}
if (!asmNum(tokens[3], (unsigned int *) &simm)) {
return msgs[7];
}
if ((simm & 0x00000003) != 0) {
return msgs[9];
}
simm -= addr + 4;
simm /= 4;
if (simm >= (signed) (1 << 15) ||
simm < - (signed) (1 << 15)) {
return msgs[10];
}
result = ((Word) instr->opcode << 26) |
(r1 << 21) |
(r2 << 16) |
(simm & MASK(16));
break;
case FORMAT_J:
/* no registers and a 26 bit signed offset operand */
if (n > 2) {
return msgs[4];
}
if (n < 2) {
return msgs[5];
}
if (!asmNum(tokens[1], (unsigned int *) &simm)) {
return msgs[7];
}
if ((simm & 0x00000003) != 0) {
return msgs[9];
}
simm -= addr + 4;
simm /= 4;
if (simm >= (signed) (1 << 25) ||
simm < - (signed) (1 << 25)) {
return msgs[10];
}
result = ((Word) instr->opcode << 26) |
(simm & MASK(26));
break;
case FORMAT_JR:
/* one register operand */
if (n > 2) {
return msgs[4];
}
if (n < 2) {
return msgs[5];
}
if (!asmReg(tokens[1], &r1)) {
return msgs[6];
}
result = ((Word) instr->opcode << 26) |
(r1 << 21);
break;
default:
return msgs[3];
}
/* line successfully assembled */
*instrPtr = result;
return NULL;
}
/common/keyboard.s
0,0 → 1,149
;
; keyboard.s -- a PC keyboard as input device
;
 
;***************************************************************
 
.set kbdbase,0xF0200000 ; keyboard base address
 
; .import cout
; .import byteout
 
.import xltbl1 ; kbd translation table 1
.import xltbl2 ; kbd translation table 2
 
.export kbdinit ; initialize keyboard
.export kbdinchk ; check if input available
.export kbdin ; do keyboard input
 
;***************************************************************
 
.code
.align 4
 
kbdinit:
jr $31
 
kbdinchk:
add $8,$0,kbdbase
ldw $2,$8,0
and $2,$2,1
jr $31
 
kbdin:
sub $29,$29,12
stw $31,$29,8
stw $16,$29,4
stw $17,$29,0
kbdin0:
jal kbdinp
add $16,$2,$0 ; key 1 in $16
add $8,$0,0xF0
bne $16,$8,kbdin2
kbdin1:
jal kbdinp
j kbdin0
kbdin2:
jal kbdinp
add $17,$2,$0 ; key 2 in $17
beq $17,$16,kbdin2
add $8,$0,0xF0
beq $17,$8,kbdin3
j kbdin5
kbdin3:
jal kbdinp
bne $2,$16,kbdin2
kbdin4:
add $4,$16,$0 ; use key 1
add $5,$0,xltbl1 ; with translation table 1
jal xlat
j kbdx
kbdin5:
jal kbdinp
add $8,$0,0xF0
bne $2,$8,kbdin5
kbdin6:
jal kbdinp
beq $2,$16,kbdin7
beq $2,$17,kbdin9
j kbdin5
kbdin7:
jal kbdinp
add $8,$0,0xF0
bne $2,$8,kbdin7
kbdin8:
jal kbdinp
bne $2,$17,kbdin7
j kbdin11
kbdin9:
jal kbdinp
add $8,$0,0xF0
bne $2,$8,kbdin9
kbdin10:
jal kbdinp
bne $2,$16,kbdin9
j kbdin11
kbdin11:
add $8,$0,0x12 ; left shift key
beq $16,$8,kbdin12
add $8,$0,0x59 ; right shift key
beq $16,$8,kbdin12
add $8,$0,0x14 ; ctrl key
beq $16,$8,kbdin14
j kbdin13
kbdin12:
add $4,$17,$0 ; use key 2
add $5,$0,xltbl2 ; with translation table 2
jal xlat
j kbdx
kbdin13:
add $4,$16,$0 ; use key 1
add $5,$0,xltbl1 ; with translation table 1
jal xlat
j kbdx
kbdin14:
add $4,$17,$0 ; use key 2
add $5,$0,xltbl1 ; with translation table 1
jal xlat
and $2,$2,0xFF-0x60 ; then reset bits 0x60
j kbdx
kbdx:
ldw $17,$29,0
ldw $16,$29,4
ldw $31,$29,8
add $29,$29,12
jr $31
 
kbdinp:
add $8,$0,kbdbase
kbdinp1:
ldw $9,$8,0
and $9,$9,1
beq $9,$0,kbdinp1 ; wait until character ready
ldw $2,$8,4 ; get character
add $9,$0,0xE0
beq $2,$9,kbdinp1 ; ignore E0 prefix
add $9,$0,0xE1
beq $2,$9,kbdinp1 ; as well as E1 prefix
jr $31
 
xlat:
sub $29,$29,8
stw $31,$29,4
stw $16,$29,0
and $16,$4,0xFF
add $8,$16,$5
ldbu $2,$8,0
bne $2,$0,xlat1
; add $4,$0,'<'
; jal cout
; add $4,$16,$0
; jal byteout
; add $4,$0,'>'
; jal cout
add $2,$16,$0
xlat1:
ldw $16,$29,0
ldw $31,$29,4
add $29,$29,8
jr $31
/common/command.h
0,0 → 1,13
/*
* command.h -- command interpreter
*/
 
 
#ifndef _COMMAND_H_
#define _COMMAND_H_
 
 
void execCommand(char *line);
 
 
#endif /* _COMMAND_H_ */
/common/romlib.c
0,0 → 1,636
/*
* romlib.c -- the ROM library
*/
 
 
#include "common.h"
#include "stdarg.h"
#include "romlib.h"
#include "start.h"
 
 
/**************************************************************/
 
 
/*
* This is only for debugging.
* Place a breakpoint at the very beginning of this routine
* and call it wherever you want to break execution.
*/
void debugBreak(void) {
}
 
 
/**************************************************************/
 
 
/*
* Count the length of a string (without terminating null character).
*/
int strlen(const char *s) {
const char *p;
 
p = s;
while (*p != '\0') {
p++;
}
return p - s;
}
 
 
/*
* Compare two strings.
* Return a number < 0, = 0, or > 0 iff the first string is less
* than, equal to, or greater than the second one, respectively.
*/
int strcmp(const char *s, const char *t) {
while (*s == *t) {
if (*s == '\0') {
return 0;
}
s++;
t++;
}
return *s - *t;
}
 
 
/*
* Copy string t to string s (includes terminating null character).
*/
char *strcpy(char *s, const char *t) {
char *p;
 
p = s;
while ((*p = *t) != '\0') {
p++;
t++;
}
return s;
}
 
 
/*
* Append string t to string s.
*/
char *strcat(char *s, const char *t) {
char *p;
 
p = s;
while (*p != '\0') {
p++;
}
while ((*p = *t) != '\0') {
p++;
t++;
}
return s;
}
 
 
/*
* Locate character c in string s.
*/
char *strchr(const char *s, char c) {
while (*s != c) {
if (*s == '\0') {
return NULL;
}
s++;
}
return (char *) s;
}
 
 
/*
* Extract the next token from the string s, delimited
* by any character from the delimiter string t.
*/
char *strtok(char *s, const char *t) {
static char *p;
char *q;
 
if (s != NULL) {
p = s;
} else {
p++;
}
while (*p != '\0' && strchr(t, *p) != NULL) {
p++;
}
if (*p == '\0') {
return NULL;
}
q = p++;
while (*p != '\0' && strchr(t, *p) == NULL) {
p++;
}
if (*p != '\0') {
*p = '\0';
} else {
p--;
}
return q;
}
 
 
/**************************************************************/
 
 
/*
* Determine if a character is 'white space'.
*/
static Bool isspace(char c) {
Bool res;
 
switch (c) {
case ' ':
case '\f':
case '\n':
case '\r':
case '\t':
case '\v':
res = true;
break;
default:
res = false;
break;
}
return res;
}
 
 
/*
* Check for valid digit, and convert to value.
*/
static Bool checkDigit(char c, int base, int *value) {
if (c >= '0' && c <= '9') {
*value = c - '0';
} else
if (c >= 'A' && c <= 'Z') {
*value = c - 'A' + 10;
} else
if (c >= 'a' && c <= 'z') {
*value = c - 'a' + 10;
} else {
return false;
}
return *value < base;
}
 
 
/*
* Convert initial part of string to unsigned long integer.
*/
unsigned long strtoul(const char *s, char **endp, int base) {
unsigned long res;
int sign;
int digit;
 
res = 0;
while (isspace(*s)) {
s++;
}
if (*s == '+') {
sign = 1;
s++;
} else
if (*s == '-') {
sign = -1;
s++;
} else {
sign = 1;
}
if (base == 0 || base == 16) {
if (*s == '0' &&
(*(s + 1) == 'x' || *(s + 1) == 'X')) {
/* base is 16 */
s += 2;
base = 16;
} else {
/* base is 0 or 16, but number does not start with "0x" */
if (base == 0) {
if (*s == '0') {
s++;
base = 8;
} else {
base = 10;
}
} else {
/* take base as is */
}
}
} else {
/* take base as is */
}
while (checkDigit(*s, base, &digit)) {
res *= base;
res += digit;
s++;
}
if (endp != NULL) {
*endp = (char *) s;
}
return sign * res;
}
 
 
/**************************************************************/
 
 
/*
* Exchange two array items of a given size.
*/
static void xchg(char *p, char *q, int size) {
char t;
 
while (size--) {
t = *p;
*p++ = *q;
*q++ = t;
}
}
 
 
/*
* This is a recursive version of quicksort.
*/
static void sort(char *l, char *r, int size,
int (*cmp)(const void *, const void *)) {
char *i;
char *j;
char *x;
 
i = l;
j = r;
x = l + (((r - l) / size) / 2) * size;
do {
while (cmp(i, x) < 0) {
i += size;
}
while (cmp(x, j) < 0) {
j -= size;
}
if (i <= j) {
/* exchange array elements i and j */
/* attention: update x if it is one of these */
if (x == i) {
x = j;
} else
if (x == j) {
x = i;
}
xchg(i, j, size);
i += size;
j -= size;
}
} while (i <= j);
if (l < j) {
sort(l, j, size, cmp);
}
if (i < r) {
sort(i, r, size, cmp);
}
}
 
 
/*
* External interface for the quicksort algorithm.
*/
void qsort(void *base, int n, int size,
int (*cmp)(const void *, const void*)) {
sort((char *) base, (char *) base + (n - 1) * size, size, cmp);
}
 
 
/**************************************************************/
 
 
/*
* Input a character from the console.
*/
char getchar(void) {
return cin();
}
 
 
/*
* Output a character on the console.
* Replace LF by CR/LF.
*/
void putchar(char c) {
if (c == '\n') {
cout('\r');
}
cout(c);
}
 
 
/*
* Output a string on the console.
* Replace LF by CR/LF.
*/
void puts(const char *s) {
while (*s != '\0') {
putchar(*s);
s++;
}
}
 
 
/**************************************************************/
 
 
/*
* Count the number of characters needed to represent
* a given number in base 10.
*/
static int countPrintn(long n) {
long a;
int res;
 
res = 0;
if (n < 0) {
res++;
n = -n;
}
a = n / 10;
if (a != 0) {
res += countPrintn(a);
}
return res + 1;
}
 
 
/*
* Output a number in base 10.
*/
static void *printn(void *(*emit)(void *, char), void *arg,
int *nchar, long n) {
long a;
 
if (n < 0) {
arg = emit(arg, '-');
(*nchar)++;
n = -n;
}
a = n / 10;
if (a != 0) {
arg = printn(emit, arg, nchar, a);
}
arg = emit(arg, n % 10 + '0');
(*nchar)++;
return arg;
}
 
 
/*
* Count the number of characters needed to represent
* a given number in a given base.
*/
static int countPrintu(unsigned long n, unsigned long b) {
unsigned long a;
int res;
 
res = 0;
a = n / b;
if (a != 0) {
res += countPrintu(a, b);
}
return res + 1;
}
 
 
/*
* Output a number in a given base.
*/
static void *printu(void *(*emit)(void *, char), void *arg,
int *nchar, unsigned long n, unsigned long b,
Bool upperCase) {
unsigned long a;
 
a = n / b;
if (a != 0) {
arg = printu(emit, arg, nchar, a, b, upperCase);
}
if (upperCase) {
arg = emit(arg, "0123456789ABCDEF"[n % b]);
(*nchar)++;
} else {
arg = emit(arg, "0123456789abcdef"[n % b]);
(*nchar)++;
}
return arg;
}
 
 
/*
* Output a number of filler characters.
*/
static void *fill(void *(*emit)(void *, char), void *arg,
int *nchar, int numFillers, char filler) {
while (numFillers-- > 0) {
arg = emit(arg, filler);
(*nchar)++;
}
return arg;
}
 
 
/*
* This function does the real work of formatted printing.
*/
static int doPrintf(void *(*emit)(void *, char), void *arg,
const char *fmt, va_list ap) {
int nchar;
char c;
int n;
long ln;
unsigned int u;
unsigned long lu;
char *s;
Bool negFlag;
char filler;
int width, count;
 
nchar = 0;
while (1) {
while ((c = *fmt++) != '%') {
if (c == '\0') {
return nchar;
}
arg = emit(arg, c);
nchar++;
}
c = *fmt++;
if (c == '-') {
negFlag = true;
c = *fmt++;
} else {
negFlag = false;
}
if (c == '0') {
filler = '0';
c = *fmt++;
} else {
filler = ' ';
}
width = 0;
while (c >= '0' && c <= '9') {
width *= 10;
width += c - '0';
c = *fmt++;
}
if (c == 'd') {
n = va_arg(ap, int);
count = countPrintn(n);
if (width > 0 && !negFlag) {
arg = fill(emit, arg, &nchar, width - count, filler);
}
arg = printn(emit, arg, &nchar, n);
if (width > 0 && negFlag) {
arg = fill(emit, arg, &nchar, width - count, filler);
}
} else
if (c == 'u' || c == 'o' || c == 'x' || c == 'X') {
u = va_arg(ap, int);
count = countPrintu(u,
c == 'o' ? 8 : ((c == 'x' || c == 'X') ? 16 : 10));
if (width > 0 && !negFlag) {
arg = fill(emit, arg, &nchar, width - count, filler);
}
arg = printu(emit, arg, &nchar, u,
c == 'o' ? 8 : ((c == 'x' || c == 'X') ? 16 : 10),
c == 'X');
if (width > 0 && negFlag) {
arg = fill(emit, arg, &nchar, width - count, filler);
}
} else
if (c == 'l') {
c = *fmt++;
if (c == 'd') {
ln = va_arg(ap, long);
count = countPrintn(ln);
if (width > 0 && !negFlag) {
arg = fill(emit, arg, &nchar, width - count, filler);
}
arg = printn(emit, arg, &nchar, ln);
if (width > 0 && negFlag) {
arg = fill(emit, arg, &nchar, width - count, filler);
}
} else
if (c == 'u' || c == 'o' || c == 'x' || c == 'X') {
lu = va_arg(ap, long);
count = countPrintu(lu,
c == 'o' ? 8 : ((c == 'x' || c == 'X') ? 16 : 10));
if (width > 0 && !negFlag) {
arg = fill(emit, arg, &nchar, width - count, filler);
}
arg = printu(emit, arg, &nchar, lu,
c == 'o' ? 8 : ((c == 'x' || c == 'X') ? 16 : 10),
c == 'X');
if (width > 0 && negFlag) {
arg = fill(emit, arg, &nchar, width - count, filler);
}
} else {
arg = emit(arg, 'l');
nchar++;
arg = emit(arg, c);
nchar++;
}
} else
if (c == 's') {
s = va_arg(ap, char *);
count = strlen(s);
if (width > 0 && !negFlag) {
arg = fill(emit, arg, &nchar, width - count, filler);
}
while ((c = *s++) != '\0') {
arg = emit(arg, c);
nchar++;
}
if (width > 0 && negFlag) {
arg = fill(emit, arg, &nchar, width - count, filler);
}
} else
if (c == 'c') {
c = va_arg(ap, char);
arg = emit(arg, c);
nchar++;
} else {
arg = emit(arg, c);
nchar++;
}
}
/* never reached */
return 0;
}
 
 
/*
* Emit a character to the console.
*/
static void *emitToConsole(void *dummy, char c) {
putchar(c);
return dummy;
}
 
 
/*
* Formatted output with a variable argument list.
*/
int vprintf(const char *fmt, va_list ap) {
int n;
 
n = doPrintf(emitToConsole, NULL, fmt, ap);
return n;
}
 
 
/*
* Formatted output.
*/
int printf(const char *fmt, ...) {
int n;
va_list ap;
 
va_start(ap, fmt);
n = vprintf(fmt, ap);
va_end(ap);
return n;
}
 
 
/*
* Emit a character to a buffer.
*/
static void *emitToBuffer(void *bufptr, char c) {
*(char *)bufptr = c;
return (char *) bufptr + 1;
}
 
 
/*
* Formatted output into a buffer with a variable argument list.
*/
int vsprintf(char *s, const char *fmt, va_list ap) {
int n;
 
n = doPrintf(emitToBuffer, s, fmt, ap);
s[n] = '\0';
return n;
}
 
 
/*
* Formatted output into a buffer.
*/
int sprintf(char *s, const char *fmt, ...) {
int n;
va_list ap;
 
va_start(ap, fmt);
n = vsprintf(s, fmt, ap);
va_end(ap);
return n;
}
/common/display.s
0,0 → 1,225
;
; display.s -- a memory-mapped alphanumerical display
;
 
;***************************************************************
 
.set dspbase,0xF0100000 ; display base address
 
.export dspinit ; initialize display
.export dspoutchk ; check for output possible
.export dspout ; do display output
 
;***************************************************************
 
.code
.align 4
 
; initialize display
dspinit:
sub $29,$29,4
stw $31,$29,0
jal clrscr
add $8,$0,scrrow
stw $0,$8,0
add $8,$0,scrcol
stw $0,$8,0
jal calcp
jal stcrs
ldw $31,$29,0
add $29,$29,4
jr $31
 
; check if a character can be written
dspoutchk:
add $2,$0,1
jr $31
 
; output a character on the display
dspout:
sub $29,$29,8
stw $31,$29,4
stw $16,$29,0
and $16,$4,0xFF
jal rmcrs
add $8,$0,' '
bltu $16,$8,dspout2
add $8,$0,scrptr
ldw $9,$8,0
or $16,$16,0x07 << 8
stw $16,$9,0
add $9,$9,4
stw $9,$8,0
add $8,$0,scrcol
ldw $9,$8,0
add $9,$9,1
stw $9,$8,0
add $10,$0,80
bne $9,$10,dspout1
jal docr
jal dolf
dspout1:
jal stcrs
ldw $16,$29,0
ldw $31,$29,4
add $29,$29,8
jr $31
 
dspout2:
add $8,$0,0x0D
bne $16,$8,dspout3
jal docr
j dspout1
 
dspout3:
add $8,$0,0x0A
bne $16,$8,dspout4
jal dolf
j dspout1
 
dspout4:
add $8,$0,0x08
bne $16,$8,dspout5
jal dobs
j dspout1
 
dspout5:
j dspout1
 
; do carriage return
docr:
sub $29,$29,4
stw $31,$29,0
add $8,$0,scrcol
stw $0,$8,0
jal calcp
ldw $31,$29,0
add $29,$29,4
jr $31
 
; do linefeed
dolf:
sub $29,$29,4
stw $31,$29,0
add $8,$0,scrrow
ldw $9,$8,0
add $10,$0,29
beq $9,$10,dolf1
add $9,$9,1
stw $9,$8,0
jal calcp
j dolf2
dolf1:
jal scrscr
dolf2:
ldw $31,$29,0
add $29,$29,4
jr $31
 
; do backspace
dobs:
sub $29,$29,4
stw $31,$29,0
add $8,$0,scrcol
ldw $9,$8,0
beq $9,$0,dobs1
sub $9,$9,1
stw $9,$8,0
jal calcp
dobs1:
ldw $31,$29,0
add $29,$29,4
jr $31
 
; remove cursor
rmcrs:
add $8,$0,scrptr
ldw $8,$8,0
add $9,$0,scrchr
ldw $10,$9,0
stw $10,$8,0
jr $31
 
; set cursor
stcrs:
add $8,$0,scrptr
ldw $8,$8,0
add $9,$0,scrchr
ldw $10,$8,0
stw $10,$9,0
add $10,$0,(0x87 << 8) | '_'
stw $10,$8,0
jr $31
 
; calculate screen pointer based on row and column
calcp:
add $9,$0,dspbase
add $8,$0,scrrow
ldw $10,$8,0
sll $10,$10,7+2
add $9,$9,$10
add $8,$0,scrcol
ldw $10,$8,0
sll $10,$10,0+2
add $9,$9,$10
add $8,$0,scrptr
stw $9,$8,0
jr $31
 
; clear screen
clrscr:
add $11,$0,(0x07 << 8) | ' '
add $8,$0,dspbase
add $9,$0,30
clrscr1:
add $10,$0,80
clrscr2:
stw $11,$8,0
add $8,$8,4
sub $10,$10,1
bne $10,$0,clrscr2
add $8,$8,(128-80)*4
sub $9,$9,1
bne $9,$0,clrscr1
jr $31
 
; scroll screen
scrscr:
add $8,$0,dspbase
add $9,$0,29
scrscr1:
add $10,$0,80
scrscr2:
ldw $11,$8,128*4
stw $11,$8,0
add $8,$8,4
sub $10,$10,1
bne $10,$0,scrscr2
add $8,$8,(128-80)*4
sub $9,$9,1
bne $9,$0,scrscr1
add $11,$0,(0x07 << 8) | ' '
add $10,$0,80
scrscr3:
stw $11,$8,0
add $8,$8,4
sub $10,$10,1
bne $10,$0,scrscr3
jr $31
 
;***************************************************************
 
.bss
.align 4
 
scrptr:
.word 0
 
scrrow:
.word 0
 
scrcol:
.word 0
 
scrchr:
.word 0
/common/disasm.h
0,0 → 1,13
/*
* disasm.h -- disassembler
*/
 
 
#ifndef _DISASM_H_
#define _DISASM_H_
 
 
char *disasm(Word instr, Word locus);
 
 
#endif /* _DISASM_H_ */
/common/asm.h
0,0 → 1,13
/*
* asm.h -- assembler
*/
 
 
#ifndef _ASM_H_
#define _ASM_H_
 
 
char *asmInstr(char *line, Word addr, Word *instrPtr);
 
 
#endif /* _ASM_H_ */
/common/end.s
0,0 → 1,19
;
; end.s -- end-of-segment labels
;
 
.export _ecode
.export _edata
.export _ebss
 
.code
.align 4
_ecode:
 
.data
.align 4
_edata:
 
.bss
.align 4
_ebss:
/common/getline.c
0,0 → 1,136
/*
* getline.c -- line input
*/
 
 
#include "common.h"
#include "stdarg.h"
#include "romlib.h"
#include "getline.h"
 
 
#define MAX_HISTORY 20
 
 
static char history[MAX_HISTORY][80];
static int historyIndex; /* next line to be written */
 
 
/*
* Get a line from the console.
*/
char *getLine(char *prompt) {
static char line[80];
int index;
int historyPointer;
char c;
int i;
 
printf(prompt);
index = 0;
historyPointer = historyIndex;
while (1) {
c = getchar();
switch (c) {
case '\r':
putchar('\n');
line[index] = '\0';
return line;
case '\b':
case 0x7F:
if (index == 0) {
break;
}
putchar('\b');
putchar(' ');
putchar('\b');
index--;
break;
case 'P' & ~0x40:
if (historyPointer == historyIndex) {
line[index] = '\0';
strcpy(history[historyIndex], line);
}
i = historyPointer - 1;
if (i == -1) {
i = MAX_HISTORY - 1;
}
if (i == historyIndex) {
putchar('\a');
break;
}
if (history[i][0] == '\0') {
putchar('\a');
break;
}
historyPointer = i;
strcpy(line, history[historyPointer]);
printf("\r");
for (i = 0; i < 79; i++) {
printf(" ");
}
printf("\r");
printf(prompt);
printf(line);
index = strlen(line);
break;
case 'N' & ~0x40:
if (historyPointer == historyIndex) {
putchar('\a');
break;
}
i = historyPointer + 1;
if (i == MAX_HISTORY) {
i = 0;
}
historyPointer = i;
strcpy(line, history[historyPointer]);
printf("\r");
for (i = 0; i < 79; i++) {
printf(" ");
}
printf("\r");
printf(prompt);
printf(line);
index = strlen(line);
break;
default:
if (c == '\t') {
c = ' ';
}
if (c < 0x20 || c > 0x7E) {
break;
}
putchar(c);
line[index++] = c;
break;
}
}
/* never reached */
return NULL;
}
 
 
/*
* Add a line to the history.
* Don't do this if the line is empty, or if its
* contents exactly match the previous line.
*/
void addHist(char *line) {
int lastWritten;
 
if (*line == '\0') {
return;
}
lastWritten = historyIndex - 1;
if (lastWritten == -1) {
lastWritten = MAX_HISTORY - 1;
}
if (strcmp(history[lastWritten], line) == 0) {
return;
}
strcpy(history[historyIndex], line);
if (++historyIndex == MAX_HISTORY) {
historyIndex = 0;
}
}
/common/romlib.h
0,0 → 1,34
/*
* romlib.h -- the ROM library
*/
 
 
#ifndef _ROMLIB_H_
#define _ROMLIB_H_
 
 
void debugBreak(void);
 
int strlen(const char *s);
int strcmp(const char *s, const char *t);
char *strcpy(char *s, const char *t);
char *strcat(char *s, const char *t);
char *strchr(const char *s, char c);
char *strtok(char *s, const char *t);
 
unsigned long strtoul(const char *s, char **endp, int base);
 
void qsort(void *base, int n, int size,
int (*cmp)(const void *, const void *));
 
char getchar(void);
void putchar(char c);
void puts(const char *s);
 
int vprintf(const char *fmt, va_list ap);
int printf(const char *fmt, ...);
int vsprintf(char *s, const char *fmt, va_list ap);
int sprintf(char *s, const char *fmt, ...);
 
 
#endif /* _ROMLIB_H_ */
/common/stdarg.h
0,0 → 1,41
/*
* stdarg.h -- variable argument lists
*/
 
 
#ifndef _STDARG_H_
#define _STDARG_H_
 
 
typedef char *va_list;
 
 
static float __va_arg_tmp;
 
 
#define va_start(list, start) \
((void)((list) = (sizeof(start)<4 ? \
(char *)((int *)&(start)+1) : (char *)(&(start)+1))))
 
#define __va_arg(list, mode, n) \
(__typecode(mode)==1 && sizeof(mode)==4 ? \
(__va_arg_tmp = *(double *)(&(list += \
((sizeof(double)+n)&~n))[-(int)((sizeof(double)+n)&~n)]), \
*(mode *)&__va_arg_tmp) : \
*(mode *)(&(list += \
((sizeof(mode)+n)&~n))[-(int)((sizeof(mode)+n)&~n)]))
 
#define _bigendian_va_arg(list, mode, n) \
(sizeof(mode)==1 ? *(mode *)(&(list += 4)[-1]) : \
sizeof(mode)==2 ? *(mode *)(&(list += 4)[-2]) : \
__va_arg(list, mode, n))
 
#define va_end(list) ((void)0)
 
#define va_arg(list, mode) \
(sizeof(mode)==8 ? \
*(mode *)(&(list = (char*)(((int)list + 15)&~7U))[-8]) : \
_bigendian_va_arg(list, mode, 3U))
 
 
#endif /* _STDARG_H_ */
/common/getline.h
0,0 → 1,14
/*
* getline.h -- line input
*/
 
 
#ifndef _GETLINE_H_
#define _GETLINE_H_
 
 
char *getLine(char *prompt);
void addHist(char *line);
 
 
#endif /* _GETLINE_H_ */
/common/cpu.h
0,0 → 1,40
/*
* cpu.h -- execute instructions
*/
 
 
#ifndef _CPU_H_
#define _CPU_H_
 
 
#define PSW_V 0x08000000 /* interrupt vector bit in PSW */
#define PSW_UM 0x04000000 /* user mode enable bit in PSW */
#define PSW_PUM 0x02000000 /* previous value of PSW_UM */
#define PSW_OUM 0x01000000 /* old value of PSW_UM */
#define PSW_IE 0x00800000 /* interrupt enable bit in PSW */
#define PSW_PIE 0x00400000 /* previous value of PSW_IE */
#define PSW_OIE 0x00200000 /* old value of PSW_IE */
#define PSW_PRIO_MASK 0x001F0000 /* bits to encode IRQ prio in PSW */
 
 
Word cpuGetPC(void);
void cpuSetPC(Word addr);
 
Word cpuGetReg(int regnum);
void cpuSetReg(int regnum, Word value);
 
Word cpuGetPSW(void);
void cpuSetPSW(Word value);
 
Bool cpuTestBreak(void);
Word cpuGetBreak(void);
void cpuSetBreak(Word addr);
void cpuResetBreak(void);
 
char *exceptionToString(int exception);
 
void cpuStep(void);
void cpuRun(void);
 
 
#endif /* _CPU_H_ */
/common/common.h
0,0 → 1,27
/*
* common.h -- common definitions
*/
 
 
#ifndef _COMMON_H_
#define _COMMON_H_
 
 
#define PAGE_SHIFT 12 /* log2 of page size */
#define PAGE_SIZE (1 << PAGE_SHIFT) /* page size in bytes */
#define OFFSET_MASK (PAGE_SIZE - 1) /* mask for offset in page */
#define PAGE_MASK (~OFFSET_MASK) /* mask for page number */
 
 
typedef enum { false, true } Bool; /* truth values */
 
 
typedef unsigned int Word; /* 32 bit quantities */
typedef unsigned short Half; /* 16 bit quantities */
typedef unsigned char Byte; /* 8 bit quantities */
 
 
#define NULL ((void *) 0)
 
 
#endif /* _COMMON_H_ */
/kbdtbls/Makefile
0,0 → 1,18
#
# Makefile to construct the keyboard mapping tables
#
 
.PHONY: all install clean
 
all: kbdtbls.s
 
install: kbdtbls.s
 
kbdtbls.s: mkkbdtbls
./mkkbdtbls >kbdtbls.s
 
mkkbdtbls: mkkbdtbls.c
gcc -m32 -g -Wall -o mkkbdtbls mkkbdtbls.c
 
clean:
rm -f *~ mkkbdtbls kbdtbls.s
/kbdtbls/mkkbdtbls.c
0,0 → 1,171
/*
* mkkbdtbls.c -- construct keyboard translation tables
*/
 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
 
typedef struct {
unsigned char ascii;
unsigned char key;
} Entry;
 
 
Entry tbl1[] = {
{ 0x1B, 0x76 },
{ '1', 0x16 },
{ '2', 0x1E },
{ '3', 0x26 },
{ '4', 0x25 },
{ '5', 0x2E },
{ '6', 0x36 },
{ '7', 0x3D },
{ '8', 0x3E },
{ '9', 0x46 },
{ '0', 0x45 },
{ '^', 0x0E },
{ 0x08, 0x66 },
{ 0x09, 0x0D },
{ 'q', 0x15 },
{ 'w', 0x1D },
{ 'e', 0x24 },
{ 'r', 0x2D },
{ 't', 0x2C },
{ 'z', 0x35 },
{ 'u', 0x3C },
{ 'i', 0x43 },
{ 'o', 0x44 },
{ 'p', 0x4D },
{ '\r', 0x5A },
{ ' ', 0x29 },
{ 'a', 0x1C },
{ 's', 0x1B },
{ 'd', 0x23 },
{ 'f', 0x2B },
{ 'g', 0x34 },
{ 'h', 0x33 },
{ 'j', 0x3B },
{ 'k', 0x42 },
{ 'l', 0x4B },
{ 'y', 0x1A },
{ 'x', 0x22 },
{ 'c', 0x21 },
{ 'v', 0x2A },
{ 'b', 0x32 },
{ 'n', 0x31 },
{ 'm', 0x3A },
{ ',', 0x41 },
{ '.', 0x49 },
{ '-', 0x4A },
{ '+', 0x5B },
{ '#', 0x5D },
{ '<', 0x61 },
};
 
 
Entry tbl2[] = {
{ 0x1B, 0x76 },
{ '!', 0x16 },
{ '"', 0x1E },
{ '3', 0x26 },
{ '$', 0x25 },
{ '%', 0x2E },
{ '&', 0x36 },
{ '/', 0x3D },
{ '(', 0x3E },
{ ')', 0x46 },
{ '=', 0x45 },
{ '^', 0x0E },
{ 0x08, 0x66 },
{ 0x09, 0x0D },
{ 'Q', 0x15 },
{ 'W', 0x1D },
{ 'E', 0x24 },
{ 'R', 0x2D },
{ 'T', 0x2C },
{ 'Z', 0x35 },
{ 'U', 0x3C },
{ 'I', 0x43 },
{ 'O', 0x44 },
{ 'P', 0x4D },
{ '\r', 0x5A },
{ ' ', 0x29 },
{ 'A', 0x1C },
{ 'S', 0x1B },
{ 'D', 0x23 },
{ 'F', 0x2B },
{ 'G', 0x34 },
{ 'H', 0x33 },
{ 'J', 0x3B },
{ 'K', 0x42 },
{ 'L', 0x4B },
{ 'Y', 0x1A },
{ 'X', 0x22 },
{ 'C', 0x21 },
{ 'V', 0x2A },
{ 'B', 0x32 },
{ 'N', 0x31 },
{ 'M', 0x3A },
{ ';', 0x41 },
{ ':', 0x49 },
{ '_', 0x4A },
{ '*', 0x5B },
{ '\'', 0x5D },
{ '>', 0x61 },
};
 
 
int main(void) {
unsigned char codes[256];
int i, j;
 
for (i = 0; i < 256; i++) {
codes[i] = '\0';
}
for (i = 0; i < sizeof(tbl1)/sizeof(tbl1[0]); i++) {
codes[tbl1[i].key] = tbl1[i].ascii;
}
printf(";\n");
printf("; keyboard code tables\n");
printf(";\n");
printf("\n");
printf("\t.export\txltbl1\n");
printf("\t.export\txltbl2\n");
printf("\n");
printf("\t.code\n");
printf("\t.align\t4\n");
printf("\n");
printf("xltbl1:\n");
for (i = 0; i < 32; i++) {
printf("\t.byte\t");
for (j = 0; j < 8; j++) {
printf("0x%02X", codes[i * 8 + j]);
if (j < 7) {
printf(", ");
}
}
printf("\n");
}
printf("\n");
for (i = 0; i < 256; i++) {
codes[i] = '\0';
}
for (i = 0; i < sizeof(tbl2)/sizeof(tbl2[0]); i++) {
codes[tbl2[i].key] = tbl2[i].ascii;
}
printf("xltbl2:\n");
for (i = 0; i < 32; i++) {
printf("\t.byte\t");
for (j = 0; j < 8; j++) {
printf("0x%02X", codes[i * 8 + j]);
if (j < 7) {
printf(", ");
}
}
printf("\n");
}
return 0;
}
/copy/copy.s
0,0 → 1,34
;
; copy.s -- copy a program from ROM to RAM before executing it
;
 
.set dst,0xC0000000 ; destination is start of RAM
.set len,0x0000FF00 ; number of bytes to be copied
 
.set PSW,0 ; reg # of PSW
 
reset:
j start
 
interrupt:
j interrupt ; we better have no interrupts
 
userMiss:
j userMiss ; and no user TLB misses
 
start:
mvts $0,PSW ; disable interrupts and user mode
add $8,$0,src
add $9,$0,dst
add $10,$9,len
loop:
ldw $11,$8,0 ; copy word
stw $11,$9,0
add $8,$8,4 ; bump pointers
add $9,$9,4
bltu $9,$10,loop ; more?
add $8,$0,dst ; start execution
jr $8
 
; the program to be copied follows immediately
src:
/copy/Makefile
0,0 → 1,21
#
# Makefile for ROM-to-RAM copy program
#
 
BUILD = ../../../build
 
.PHONY: all install clean
 
all: copy.bin
 
install: copy.bin
 
copy.bin: copy.o
$(BUILD)/bin/ld -o copy.bin -m copy.map \
-h -rc 0xE0000000 copy.o
 
copy.o: copy.s
$(BUILD)/bin/as -o copy.o copy.s
 
clean:
rm -f *~ copy.o copy.bin copy.map
/Makefile
0,0 → 1,25
#
# Makefile for building the ECO32 ROM monitor
#
 
BUILD = ../../build
 
DIRS = copy kbdtbls boards
 
.PHONY: all install clean
 
all:
for i in $(DIRS) ; do \
$(MAKE) -C $$i all ; \
done
 
install:
for i in $(DIRS) ; do \
$(MAKE) -C $$i install ; \
done
 
clean:
for i in $(DIRS) ; do \
$(MAKE) -C $$i clean ; \
done
rm -f *~

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.