home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Acorn User 4
/
AUCD4.iso
/
utils
/
programing
/
babe
/
!Babe
/
emu
(
.txt
)
< prev
next >
Wrap
RISC OS BBC BASIC V Source
|
1998-03-27
|
27KB
|
675 lines
Project commenced 10/1/98
Initialise_Emu
Assign variables
set up emu mode of operation Display
1= normal y
2= stepped y
3= realistic time y
4= fast until cycle X y
mode%=1
xcycle%=10
Fa=5 :
accumulator SSEM should it be??????
2c=6 :
control instruction (CI) ARM
3p=7 :
present instruction (PI) SSEM
y=8 :
loop counter
3s=9 :
store memory SSEM
2cycle=10 :
cycle counter ARM
Problem:
For ARM chip, MSB is bit 0
For SSEM MSB is bit 31
INPUT "Enter object code filename: "; file$
file$="mem:$.obj"
!Axalign%=7 :
number of 8 pixels to shift display to the right
yalign%=5
Assemble
PROCLoadObjectFile(file$) :REM must load after assembling
PROCSaveCode("mem:$.BabyCode")
CALL start
Assemble
pass%=0
P%=code%
[OPT pass%
.start
2' STMFD R13!,{R0-R12,R14}
3@ Swi 256+22 ;
22 changes mode
49 Swi 256+28 ;to mode 28
5E Swi "OS_RemoveCursors" ;remove flashing cursor
6! Adr R0,_screen%
7! Adr R1,_screen%
8H Swi "OS_ReadVduVariables" ;get screen memory address
:L Adr s,_store ;setup pointer to store memory
; B initialise
._store
>I;32*32 bit lines, kept in this form to allow easy poking of the store
?M;lines numbered 0-31, bits numbered 0-31 from left to right, bit 0 is LSB
@E EQUD0:EQUD0:EQUD0:EQUD0:EQUD0:EQUD0:EQUD0:EQUD0
AE EQUD0:EQUD0:EQUD0:EQUD0:EQUD0:EQUD0:EQUD0:EQUD0
BE EQUD0:EQUD0:EQUD0:EQUD0:EQUD0:EQUD0:EQUD0:EQUD0
CE EQUD0:EQUD0:EQUD0:EQUD0:EQUD0:EQUD0:EQUD0:EQUD0
._starttime EQUD 0
G#._version :=v$:=0:ALIGN
.initialise
P, Swi "OS_ReadMonotonicTime"
QG Str R0,_starttime ;save time at start
S9 Mov c,#0 ;set c to 0
T9 Mov a,#0 ;set a to 0
U9 Mov p,#0 ;set p to 0
V= Mov cycle,#0 ;set cycle to 0
BL display
.fetchexecute
Y8 ;in accordance with SSEM, c always starts as 1
Z: Add c,c,#1 ;increment c
[$ Add cycle,cycle,#1
]9 ;must loop CI round if >31 ie.
c>31
c=-31
Cmp c,#31
SubGt c,c,#31
;fetch instruction
bL Mov R0,c,ASL #2 ;c*4 to get real instr address
cJ ;ie. points to word in store
d@ Ldr p,[s,R0] ;load p from store
f? ;get actline by masking out all bits except 0,1,2,3,4
g) ;put result in R1 to pass to fn
h= And R1,p,#%11111000000000000000000000000000
iM ;
E actline could be reversed before passing to fn for shorter code
jN ;but then CMP & STP don't use actline, so pass it 'as is' for speed.
lF ;get function number by masking out all bits except 13,14,15
m= And R0,p,#%00000000000001110000000000000000
o2 ;shift right to get ARM number (MSB 1st)
pP ;but only by 14 in order that fn number points to a word for jumptable
qG ;ie. now looks like %000000000000000000000000000xyz00 for ARM
rF ;on SSEB would be taken as %xyz00000000000000000000000000000
tM Add PC,PC,R0,ASR #14 ;jump to position in jump table
uF Mov R0,R0 ;NoOp to allow jumptable
.jumptable
w7 ;NB- since SSEB is LSB 1st and ARM is MSB 1st
x0 ;the
table is not in
number order.
yI ;It is in the order of the MSB 1st interpretation of the binary
zF ;don't use BL as fn will B back to endoftable at end of code
{4 B jmp_fn ;000 0
|4 B sub_fn ;001 4
}4 B ldn_fn ;010 2
~4 B cmp_fn ;011 6
4 B jrp_fn ;100 1
O B sb5_fn ;101 5 (fn 5 is the same as fn 4)
4 B sto_fn ;110 3
4 B stp_fn ;111 7
.endoftable
@ ;display CI and
Ldr R0,_mode%
Cmp R0,#0
D BLNe draw_ci ;as these alter after
D BLNe draw_pi ;every fetch execute!
J Swi 256+31 ;
31 (position text cursor)
Swi 256+0
Swi 256+37
% Adr R0,_cyclestring
! Swi "OS_Write0"
Mov R0,cycle
# BL Print32BitDec
Mov R0,#121
7 Mov R1,#81
&80 ;keycode for S
Swi "OS_Byte"
Cmp R1,#&FF
BLEq screenshot
Ldr R0,_stop
Cmp R0,#1
! AdrEq R0,_stopset
" SwiEq "OS_NewLine"
! SwiEq "OS_Write0"
" SwiEq "OS_NewLine"
! BEq end_program
3 ;check for stepped mode wait for keypress
Ldr R0,_mode%
Cmp R0,#4
! LdrEq R1,_xcycle%
CmpEq cycle,R1
MovEq R0,#2
StrEq R0,_mode%
Cmp R0,#2
" SwiEq "OS_NewLine"
% AdrEq R0,_pressanykey
! SwiEq "OS_Write0"
SwiEq "OS_ReadC"
;check for escape
R ;Swi "OS_ReadEscapeState" ;sets (C)arry flag if escape presed
G ;BCC fetchexecute ;if not escape then loop
Mov R0,#121
# Mov R1,#112
F Swi "OS_Byte" ;check for escape key
Cmp R1,#&FF
" BNe fetchexecute
.end_program
& ;print timer and end program
$ Adr R0,_timestring
! Swi "OS_Write0"
, Swi "OS_ReadMonotonicTime"
# Ldr R1,_starttime
Sub R0,R0,R1
# BL Print32BitDec
" Swi "OS_NewLine"
= LDMFD R13!,{R0-R12,PC}^ ; ==
PROGRAM==
._mode%
@ EQUD mode% ;mode of operation
._xcycle%
Q EQUD xcycle% ;go normal until at this no. cycle
;display all items initially
.display
' STMFD R13!,{R0-R12,R14}
I ;display text before others so that
31 does not affect layout
! Adr R0,_version
> Swi "OS_Write0" ;display version
" Swi "OS_NewLine"
" Adr R0,_cistring
! Swi "OS_Write0"
" Adr R0,_pistring
! Swi "OS_Write0"
" Adr R0,_acstring
! Swi "OS_Write0"
% Adr R0,_storestring
! Swi "OS_Write0"
;number lines in store
R Mov R1,#0 ;setup counter and number to display
.display_storenums
G Swi 256+31 ;
31 set text cursor pos
8 Swi 256+xalign%-3 ;set x pos
7 Add R0,R1,#yalign% ;set ypos
6 Swi "OS_WriteC" ;do ypos
H Mov R0,R1 ;move counter for printing
= BL Print32BitDec ;print line num
8 Swi "OS_NewLine" ;next line
E Add R1,R1,#1 ;inc counter and number
= Cmp R1,#32 ;at end of loop
< BLt display_storenums ;if not branch
+ ;end of store line number display
BL draw_ci
BL draw_pi
# BL draw_ac
B Adr R9,_store ;setup store address
H ;no point in waiting for VSync when only executed occasionally
;Mov R0,#19
< ;Swi "OS_Byte" ;
for VSync
Mov R2,#0
.displaystore_loop%
C ;this should really be optimised to work backwards rather
0 ;than having to reverse the input line
G Mov R8,R2,ASL#2 ;y*4 to get addr in store
N Ldr R1,[s,R8] ;get line into R1 for conversion
B BL Reverse32Bit ;reverse SSEM to ARM
; Add R1,R2,#yalign% ;add y offset
7 BL drawline% ;drawline
. ;R0 is set to number to disp already
H Mov R3,R0 ;temp store num to display
C Swi 256+31 ;
31 set text cursor
8 Swi 256+31+xalign%+2 ;set x pos
8 Mov R0,R1 ;set y pos
7 Swi "OS_WriteC" ;do y pos
H Mov R0,R3 ;get num for display
: BL Print32BitDec ;display num
Mov R1,R3
" BL Reverse32Bit
; Add R1,R2,#yalign% ;add y offset
BL disasm
> ;R0 and R1 should already be set to number & y pos !
< ;Add R1,R2,#yalign% ;add y offset
;Mov R0,R3
? Add R2,R2,#1 ;inc line counter
? Cmp R2,#32 ;test end of loop
? BLt displaystore_loop% ;if not loop back
/ ;print cycle counter
J Swi 256+31 ;
31 (position text cursor)
Swi 256+0
Swi 256+37
% Adr R0,_cyclestring
! Swi "OS_Write0"
Mov R0,cycle
# BL Print32BitDec
4 LDMFD R13!,{R0-R12,PC}^ ;leave
.disasm
7 ;R0 line to disassemble in SSEM order
+ ;R1 ypos to display it at
' STMFD R13!,{R0-R12,R14}
H Mov R3,R0 ;temp store num to display
!C Swi 256+31 ;
31 set text cursor
"8 Swi 256+31+xalign%+2+14 ;set x pos
#8 Mov R0,R1 ;set y pos
$7 Swi "OS_WriteC" ;do y pos
&I And R0,R3,#%00000000000001110000000000000000 ;get fn
(M Add PC,PC,R0,ASR #13 ;jump to position in jump table
)F Mov R0,R0 ;NoOp to allow jumptable
.dis_jumptable
+7 ;NB- since SSEB is LSB 1st and ARM is MSB 1st
,0 ;the
table is not in
number order.
-I ;It is in the order of the MSB 1st interpretation of the binary
.F ;don't use BL as fn will B back to endoftable at end of code
Adr R0,_fn0
0$ B dis_endoftable
Adr R0,_fn4
2$ B dis_endoftable
Adr R0,_fn2
4$ B dis_endoftable
Adr R0,_fn6
6$ B dis_endoftable
Adr R0,_fn1
8$ B dis_endoftable
Adr R0,_fn5
:$ B dis_endoftable
Adr R0,_fn3
<$ B dis_endoftable
Adr R0,_fn7
.dis_endoftable
?! Swi "OS_Write0"
A ;Adr R0,spaces
Mov R0,#
C! Swi "OS_WriteC"
EM And R1,R3,#%11111000000000000000000000000000 ;get actline
FM BL Reverse32Bit ;SSEM -> ARM
GO BL Print32BitDec ;print actline
IQ ;Adr R0,spaces ;display spaces
JO Mov R0,#
" " ;remove trailing digits
K! Swi "OS_WriteC"
M4 LDMFD R13!,{R0-R12,PC}^ ;leave
Q ._fn0 :="jmp":=0
R ._fn1 :="jrp":=0
S ._fn2 :="ldn":=0
T ._fn3 :="sto":=0
U ._fn4 :="sub":=0
V ._fn5 :="sb5":=0
W ._fn6 :="cmp":=0
X&._fn7 :="stp":=0:ALIGN
._screen%
[# Equd 148
\" Equd -1
bR;================================= Functions =================================
cG;Note- act line is passed to all fns as MSB 1st (SSEB number) in R1
.jmp_fn
;000 0
g&;copy content of storeline into CI
iJ BL Reverse32Bit ;reverse actline to ARM form
jM Mov R0,R0,ASL #2 ;actline*4 to get addr in store
kC Ldr R1,[s,R0] ;get num to copy to c
lF BL Reverse32Bit ;reverse num to ARM form
m; Mov c,R0 ;put num in c
nK B endoftable ;return to fetch-execute loop
.jrp_fn
;100 1
r#;add content of storeline to CI
tJ BL Reverse32Bit ;reverse actline to ARM form
uM Mov R0,R0,ASL #2 ;actline*4 to get addr in store
vB Ldr R1,[s,R0] ;get num to add to c
wR BL Reverse32Bit ;reverse num to add to c to ARM form
x; Add c,c,R0 ;add num to c
yK B endoftable ;return to fetch-execute loop
.ldn_fn
;010 2
}5;copy content of storeline negated to accumulator
J BL Reverse32Bit ;reverse actline to ARM form
M Mov R2,R0,ASL #2 ;actline*4 to get addr in store
N Ldr R1,[s,R2] ;get num to load as neg into acc
F BL Reverse32Bit ;reverse num to ARM form
F Rsb R1,R0,#0 ;R1=0-num (make num -ve)
G BL Reverse32Bit ;reverse num to SSEB form
J Mov a,R0 ;store number in accumulator
BL draw_ac
K B endoftable ;return to fetch-execute loop
.sto_fn
;110 3
+;copy content of accumulator into store
J BL Reverse32Bit ;reverse actline to ARM form
M Mov R1,R0,LSL #2 ;actline*4 to get addr in store
H Str a,[s,R1] ;copy accumulator to store
'MOV r3,r1 ; preserve line no.
MOV r1,a
BL Reverse32Bit ; into r0
L;Mov R0,a ;display AC since identical to line
D Mov R1,R3,ASR #2 ;get actline val again
; Add R1,R1,#yalign% ;add y offset
H BL drawline% ;draw in LEDs the new line
1 ;R0 is already set to number to display
H Mov R3,R0 ;temp store num to display
C Swi 256+31 ;
31 set text cursor
8 Swi 256+31+xalign%+2 ;set x pos
8 Mov R0,R1 ;set y pos
7 Swi "OS_WriteC" ;do y pos
B Mov R0,R3 ;get num for display
: BL Print32BitDec ;display num
* ;convert back to SSEM for disasm
Mov R1,R3
" BL Reverse32Bit
; Add R1,R2,#yalign% ;add y offset
BL disasm
K B endoftable ;return to fetch-execute loop
.sub_fn
;001 4
.sb5_fn
;101 5
3;subtract content of storeline from accumulator
* ;YUCK! Major optimisation needed
J BL Reverse32Bit ;reverse actline to ARM form
M Mov R2,R0,ASL #2 ;actline*4 to get addr in store
F Ldr R1,[s,R2] ;get num to sub from acc
F BL Reverse32Bit ;reverse num to ARM form
= Mov R4,R0 ;move num to R4
D Mov R1,a ;move acc for reversal
F BL Reverse32Bit ;reverse acc to ARM form
E Sub R1,R0,R4 ;R1=R0-R4 to get result
J BL Reverse32Bit ;reverse result to SSEM form
J Mov a,R0 ;store result in accumulator
BL draw_ac
K B endoftable ;return to fetch-execute loop
.cmp_fn
;011 6
8;skip next instruction if content of accumulator < 0
T And R0,a,#%00000000000000000000000000000001 ;mask all but sign bit
J Cmp R0,#%00000000000000000000000000000001 ;test sign bit
O AddEq c,c,#1 ;if -ve bit set then increment CI
K B endoftable ;return to fetch-execute loop
.stp_fn
;111 7
Mov R0,#1
A Str R0,_stop ;set stop flag to 1
K B endoftable ;return to fetch-execute loop
*;area to load sprites to on assembling
._sprites%
EQUD sprites%
A._at_line :=13:=10:="At store line number: ":=0:ALIGN
0._dummy :="dummy display":=0:ALIGN
%._32bit :=
0):ALIGN
0._cistring :="C I: ":=13:=10:=0:ALIGN
0._pistring :="P I: ":=13:=10:=0:ALIGN
0._acstring :="ACC: ":=13:=10:=0:ALIGN
2._storestring :="Store: ":=13:=10:=0:ALIGN
)._stopstring :="STOP: ":=0:ALIGN
*._cyclestring :="Cycle: ":=0:ALIGN
.._timestring :="Time (cs): ":=0:ALIGN
E._stopset :="The STP function has been executed":=0:ALIGN
E._pressanykey :="Press any key to continue.":=13:=10:=0:ALIGN
;on entry
7 ;R0 contains word to display (ARM version!!)
;R1 is the y pos
.drawline%
& STMFD R13!,{R0-R8,R14}
6 Mov R3,#(0+xalign%) ;starting xpos
@ Ldr R6,_screen% ;get base screen address
@ Ldr R7,_sprites% ;get base sprite address
.drawline_loop%
! ;need to preserve R0,R1
;R0 word to display
;R1 ypos
;R2 temp
;R3 xcount
! ;R4 screen address temp
! ;R5 sprite address temp
% ;R6 screen address perm Ra
% ;R7 sprite address perm Rb
;R8 temp
> Mov R4,R6 ;get screen addr
H Add R4,R4,R3,Lsl#3 ;mul by 8 to account for x
N Add R4,R4,R1,Lsl#12 ;mul by (8*640) to account for y
; Add R4,R4,R1,Lsl#10 ;and y offset
? Mov R5,R7 ;get sprites addr
K Sub R8,R3,#xalign% ;subtract align for bit shift
F Mov R8,R0,Asr R8 ;put bit needed to bit 0
A And R2,R8,#1 ;mask all but bit 0
I Add R5,R5,R2,Lsl#6 ;mul by 64 (size of sprite)
;plot sprite
! LdmIa R5!,{R2,R8}
StmIa R4,{R2,R8}
Add R4,R4,#640
! LdmIa R5!,{R2,R8}
StmIa R4,{R2,R8}
Add R4,R4,#640
! LdmIa R5!,{R2,R8}
StmIa R4,{R2,R8}
Add R4,R4,#640
! LdmIa R5!,{R2,R8}
StmIa R4,{R2,R8}
Add R4,R4,#640
! LdmIa R5!,{R2,R8}
StmIa R4,{R2,R8}
Add R4,R4,#640
! LdmIa R5!,{R2,R8}
StmIa R4,{R2,R8}
Add R4,R4,#640
! LdmIa R5!,{R2,R8}
StmIa R4,{R2,R8}
Add R4,R4,#640
! LdmIa R5!,{R2,R8}
StmIa R4,{R2,R8}
Add R4,R4,#640
;end of sprite plot
> Add R3,R3,#1 ;inc bit counter
!9 Cmp R3,#(32+xalign%) ;check loop
"F BLt drawline_loop% ;loop back if unfinished
#3 LDMFD R13!,{R0-R8,PC}^ ;leave
.draw_ci
%& STMFD R13!,{R0-R1,R14}
&& ;display control instruction
'< ;Mov R0,#1 ;line=1
( ;BL clearline
Mov R0,c
*N Swi 256+31 ;
31 position text cursor
+@ Swi 256+32+1+xalign% ;x=31+xalign
,8 Swi 256+1 ;y=1
-A BL Print32BitDec ;print number
.H Mov R1,c ;copy c for reversal
/( BL Reverse32Bit
0; Mov R1,#1 ;line 1
1= BL drawline% ;drawline
33 LDMFD R13!,{R0-R1,PC}^ ;leave
.draw_pi
6& STMFD R13!,{R0-R1,R14}
7& ;display present instruction
Mov R1,p
9" BL Reverse32Bit
:5 Mov R1,#2 ;line 2
;7 BL drawline% ;drawline
Mov R0,p
Mov R1,#2
BL disasm
?3 LDMFD R13!,{R0-R1,PC}^ ;leave
.draw_ac
B& STMFD R13!,{R0-R1,R14}
;display accumulator
D< ;Mov R0,#3 ;line=1
E ;BL clearline
FB Mov R1,a ;copy a for reversal
G" BL Reverse32Bit
H5 Mov R1,#3 ;line 3
I7 BL drawline% ;drawline
J? ;since ACC is in SSEM form then need reversed version
KH Swi 256+31 ;
31 position text cursor
L: Swi 256+32+1+xalign% ;x=31+xalign
M2 Swi 256+3 ;y=3
N; BL Print32BitDec ;print number
O4 LDMFD R13!,{R0-R1,PC}^ ;leave
Q0;store for the SSEM stop lamp 1=lit, 0=unlit
._stop
EQUD 0
U-;----------------------------------------
V-; start of assembler function definitions
X$.Reverse32Bit
reverse_32bit
Y(.Print32BitBin
print_32bitBinary
Z).Print32BitDec
print_32bitDecimal
[-;----------------------------------------
.screenshot
^& STMFD R13!,{R0-R3,R14}
_) Adr R0,inputfile_string
`! Swi "OS_Write0"
b! Adr R0,filename
Mov R1,#255
Mov R2,#0
Mov R3,#255
f# Swi "OS_ReadLine"
h' Swi 256+12 ;
i7 BL display ;do full redisplay
k' Adr R0,screensave_cli
Swi "XOS_CLI"
n4 LDMFD R13!,{R0-R3,PC}^ ;leave
.inputfile_string
q9 EQUS "Type in the filename to save as: "
EQUB 0
ALIGN
.screensave_cli
v# EQUS "SCREENSAVE "
.filename
EQUS
ALIGN
P._advert :="The Acorn Emulation Page http://www.come.to/emulate":=0
ALIGN
LoadObjectFile(file$)
blank store
x%=0
_store!(x%*4)=!zero
A=
(file$)
lines$=
count%=0
line$=
line$<>""
count%+=1
! line%=
line$,3,2))
' instr%=
("%"+
line$,6,32))
$ _store!(line%*4)=instr%
count%=
(lines$)
SaveCode(savefile$)
"SAVE "+savefile$+" "+
~(code%)+" "+
~(P%)
"SETTYPE "+savefile$+" &FFD"
Error
$;" at line ";
IF ERR<>17 THEN CHAIN "Edit:Throwback" ELSE END
===================================
Start of assembler functions
===================================
reverse_32bit
[OPT pass%
); On entry R1=32bit number to reverse
2; On exit R0=The Reversed number R1 unchanged
$; Flags - prserved
%; Other Regs - preserved
%; Intterupts - unaltered
; SVC mode - Yes
; Re-enterant- No
STMFD R13!,{R1,R14}
Mov R0,R1
LDR R1,mask5
R1,R1,R0,LSR #1
BIC R0,R0,R1,LSL #1
R R0,R1,R0,LSL #1
LDR R1,mask3
R1,R1,R0,LSR #2
BIC R0,R0,R1,LSL #2
R R0,R1,R0,LSL #2
LDR R1,mask0F
R1,R1,R0,LSR #4
BIC R0,R0,R1,LSL #4
R R0,R1,R0,LSL #4
MOV R1,#&FF
ADD R1,R1,#&FF0000
R1,R1,R0,LSR #8
BIC R0,R0,R1,LSL #8
R R0,R1,R0,LSL #8
MOV R1,R0,LSR #16
R R0,R1,R0,LSL #16
LDMFD R13!,{R1,PC}^
.mask5 DCD &55555555
.mask3 DCD &33333333
.mask0F DCD &0F0F0F0F
.zero
( EQUB 0:EQUB 0:EQUB 0:EQUB 0
===================================
print_32bitBinary
[OPT pass%
(;purpose - print 32 bit binary in R0
#; on entry R0 = number to print
& STMFD R13!,{R0-R2,R14}
Adr R1,_32bit
Mov R2,#33
@ Swi "OS_ConvertBinary4" ;convert to binary
; Swi "OS_Write0" ;print binary
& LDMFD R13!,{R0-R2,PC}^
===================================
print_32bitDecimal
[OPT pass%
0;purpose - print signed 32 bit decimal in R0
#; on entry R0 = number to print
& STMFD R13!,{R0-R2,R14}
Adr R1,_32bit
> Mov R2,#12 ;set buffer size
P Swi "OS_ConvertInteger4" ;convert int>string upto 4294967295
)SWI "OS_Write0" ; display number
0RSB r2,r2,#12 ; bytes already printed-1
.pad
CMP r2,#0
,SWI 256+32 ; trailing spaces (minimum 1)
SUBGT r2,r2,#1
BGT pad
K ;Mov R2,#
" " ;add a space onto end of string
;StrB R2,[R1]
F ;Mov R2,#0 ;move null terminator +1
! ;StrB R2,[R1,#1]
> ;Swi "OS_Write0" ;display number
& LDMFD R13!,{R0-R2,PC}^
===================================