;;;;;;;;;;;;;;;;;;;;;;;;;;
; FD803000 is an assembler modul, which is designed to support the SH7305 UBC,
; install a basic exception/interrupt-redirection frame,
; exception/interrupt-redirection seems to be extremely simple on the SH7305-calculators,
; because the SH7305-OSes use a RAM-interrupt-handler-address-table.
;
; list of references:
; [1] renesas 7705-manual REV 2.00-2003.9.19
; [2] "SHC Manual.PDF" (included in the FX9860G SDK)
; [3] renesas 7730-manual Rev.3.00 2010.09
; the 7724 is a better match for the 7305, but its manual is under NDA.
;
; it is important to set the assembler-option -cpu=sh4, to have the assembler accept the DBR-instructions.
; though, the SH7305 does not contain a FPU.
;
;;;;;;;;;;;;;;;;;;;;;;;;;;
; Hint: The formerly used RAM location 0xFD802000 cannot be used with fx-9860 SH-4 calculators. The range seems to be used by the OS on these calculators.
; The system provides for a standard wrapper, the entry point is the start of the binary.
; additionally the entrypoint is stored at offset 0x20.
; UserBreakIntHandler is the procedure, the exception/interrupt-system should be redirected to.
; the function to install the redirection is InstallUserBreak (function 8 of the jump-table).
;
;;;;;;;;;;;;;;;;;;;;;;;;;;
PROCESSOR_FAMILY: .DEFINE "SH-4A"
PROCESSOR: .DEFINE "7305"
; because there are some differences between fx-CG and fx-9860 SH-4, a Replacement Symbol OS is needed.
; it should be set in the hmake-file
.AIFDEF OS
.AELSE
.AERROR
.AENDI
;OS: .DEFINE "fxCG"
;OS: .DEFINE "fx9860"
.include "F:\CASIO\ASM_COMMON\SH_REGISTERS.SRC"
; OSfx.inc f. i. contains the syscall numbers, which are used.
.include "F:\CASIO\ASM_COMMON\OSfx.inc"
.include "F:\CASIO\ASM_COMMON\UBC.INC"
REDIRECT_EXCINT: .DEFINE "0"
REDIRECTION_EXCINT_EXAMPLE: .DEFINE "SERIAL_DUMP"
;REDIRECTION_EXCINT_EXAMPLE: .DEFINE "RAM_DUMP"
;DUMP_RAM: .DEFINE "h'880CB2D8"
;DUMP_RAM_SIZE: .DEFINE "h'00C0"
;DUMP_RAM_SIZE: .DEFINE "h'04B0"
;DUMP_RAM: .DEFINE "h'FD801450"
;DUMP_RAM_SIZE: .DEFINE "h'0040"
;DUMP_RAM: .DEFINE "h'FD801790"
;DUMP_RAM_SIZE: .DEFINE "h'0010"
;REDIRECTION_EXCINT_EXAMPLE .DEFINE "DISPLAY_REGISTERS"
PUTDISP_DD .DEFINE "1"
DRAW_WHAT: .DEFINE "VRAM"
DRAW_WITH_DELAY: .DEFINE "TRUE"
USB: .DEFINE "0"
.SECTION P,CODE,ALIGN=4
;;;;;;;;;;;;;;;;;;;;;;;;;;
Wrapper:
mov.l #TableStart, r2
SHLL2 r0
MOV.L @(r0,r2),r0
JMP @r0
NOP
?gap:
.RES.B h'20-(?gap-Wrapper)
; at offset h'20 of the binary file, the absolute wrapper address is stored
; prepared for future use
.DATA.L Wrapper
; the INT_COUNTER should stay located at offset 0x24. It is useful for basic diagnostic purposes.
INT_COUNTER .RES.L 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.SECTION D,DATA,ALIGN=4
WAIT_FOR_SERIAL .RES.L 1
NO_ERROR .EQU 0
NOT_INSTALLED_ERROR .EQU 1
ALREADY_INSTALLED_ERROR .EQU 2
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.ALIGN 4
TableStart:
.DATA.L Serial_DumpStack ; 0
.DATA.L SetInterruptHandler ; 1
.DATA.L GetInterruptHandler ; 2
.DATA.L GetTableStart ; 3
.DATA.L GetRunLibIDPtr ; 4
.DATA.L GetDBR ; 5
.DATA.L PostInstallation ; 6
.DATA.L unused_fno
.DATA.L InstallUserBreak ; 8
.DATA.L unused_fno
.DATA.L unused_fno
.DATA.L unused_fno
.SECTION P,CODE,ALIGN=4
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; int InstallUserBreak( void*ADDR )
; programs the USER BREAK CONTROLLER
; see [1], p. 562, si 12.12.2008
; see [3], p. 1016, si 12.04.2011
; if the parameter is zero, the UBC will be deactivated.
; typedef struct {
; int addr;
; int value;
; } TUBC;
; the parameter ADDR is a pointer to an array of TUBC
; the first item contains (h'55424300, 0) and is checked.
; if it is not as it should be, the UBC clock is switched off and the function quits.
; the last item contains h'55424300, h'FFFFFFFF and is checked to detect the end of the list.
; in between there are the register-addresses and values to set.
; if an register-address is zero, the item is ignored.
; "...Make sure to set all registers related to breaks before setting BBRA/BBRB." ([1], p. 555).
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
InstallUserBreak:
mov.l r14, @-r15
mov.l #h'10000000, r2
stc sr, r3
mov.l r3, @-r15
or r2, r3
ldc r3, sr ; block exceptions, interrupts and user breaks
; [1], p. 35; [3], p. 37
mov #0, r14
mov.l #WAIT_FOR_SERIAL, r3
mov #1, r0
mov.l r0, @r3
mov.l #UserBreakIntHandler, r3
ldc r3, DBR ; only possible with assembler-option cpu=sh4
; prepare UBC clock switching
mov.l #MSTPCR0, r3
mov.l @r3, r2
tst r4, r4 ; parameter valid?
bt ?UBC_Off
; the 1st item's addr-member has to be UBC_ID
mov.l @r4, r5
mov.l #UBC_ID, r0
cmp/eq r5, r0
bf ?UBC_Off
; the 1st item's value-member has to be zero
add #4, r4
mov.l @r4, r5
tst r5, r5
bt/s UBC_ON
add #4, r4
; switch Off UBC clock
?UBC_Off:
mov.l #MSTP017, r0
or r0, r2
mov.l r2, @r3
exit_InstallUserBreak
mov r14, r0
mov.l @r15+, r3
ldc r3, sr
rts
mov.l @r15+, r14
; switch ON UBC clock
UBC_ON:
mov.l #~MSTP017, r0
and r0, r2
bra ?UBC_setup_skip
mov.l r2, @r3
?UBC_setup_loop:
add #1, r14
mov.l @r4, r3
tst r3, r3 ; if addr-member is zero, then ignore
bt/s ?UBC_setup_skip
add #4, r4
mov.l #UBC_ID, r0
cmp/eq r3, r0
bt ?UBC_setup_quit
mov.l @r4, r0
mov.l #CBR0, r5
cmp/eq r3, r5
bt ?long_op
mov.l #CRR0, r5
cmp/eq r3, r5
bt ?long_op
mov.l #CAR0, r5
cmp/eq r3, r5
bt ?long_op
mov.l #CAMR0, r5
cmp/eq r3, r5
bt ?long_op
mov.l #CBR1, r5
cmp/eq r3, r5
bt ?long_op
mov.l #CRR1, r5
cmp/eq r3, r5
bt ?long_op
mov.l #CAR1, r5
cmp/eq r3, r5
bt ?long_op
mov.l #CAMR1, r5
cmp/eq r3, r5
bt ?long_op
mov.l #CDR1, r5
cmp/eq r3, r5
bt ?long_op
mov.l #CDMR1, r5
cmp/eq r3, r5
bt ?long_op
mov.l #CETR1, r5
cmp/eq r3, r5
bt ?long_op
mov.l #CCMFR, r5
cmp/eq r3, r5
bt ?long_op
mov.l #CBCR, r5
cmp/eq r3, r5
bt ?long_op
bra ?UBC_setup_skip
nop
?byte_op:
add #4, r4
mov.l @r4, r5
tst r5, r5
bf ?byte_read
bra ?UBC_setup_skip
mov.b r0, @r3
?byte_read
bra ?UBC_setup_skip
mov.b @r3, r0
?word_op:
add #4, r4
mov.l @r4, r5
tst r5, r5
bf ?word_read
bra ?UBC_setup_skip
mov.w r0, @r3
?word_read
bra ?UBC_setup_skip
mov.w @r3, r0
?long_op:
add #4, r4
mov.l @r4, r5
tst r5, r5
bf ?long_read
bra ?UBC_setup_skip
mov.l r0, @r3
?long_read
mov.l @r3, r0
?UBC_setup_skip:
bra ?UBC_setup_loop
add #4, r4
?UBC_setup_quit:
; ICBI because of [3], p. 1020, note 1 A.
XICBI 3
bra exit_InstallUserBreak
add #1, r14
.POOL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; UserBreakIntHandler
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
UserBreakIntHandler:
PUSH_EXP_BASE_REG
mov.l #h'12345678, r3
mov.l r3, @-r15
sts.l pr, @-r15
mov.l #INT_COUNTER, r3
mov.l @r3, r2
add #1, r2
mov.l r2, @r3
.AIF "PUTDISP_DD" EQ "1"
mov.l #syscall_entry, r2
mov.l #scBdisp_PutDisp_DD, r0
jsr @r2
nop
.AENDI
bsr Serial_DumpStack
nop
; mov.l #syscall_entry, r2
; mov.l #scMsgBoxPush, r0
; jsr @r2
; mov #4, r4
; mov.l #syscall_entry, r2
; mov.l #scBdisp_PutDisp_DD, r0
; jsr @r2
; nop
; mov.l #h'A44B0000, r3
; mov.w #h'4000, r2
; ?wait
; mov.w @r3, r0
; cmp/eq r2, r0
; bf ?wait
; mov.l #syscall_entry, r2
; mov.l #scMsgBoxPop, r0
; jsr @r2
; nop
lds.l @r15+, pr
mov.l @r15+, r3
POP_EXP_BASE_REG
STC SGR, R15 ; only possible with assembler-option cpu=sh4
rte
nop
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; EXPERIMENTAL REDIRECTION FUNCTION
; the routine sends the stack to the serial interface (115kBaud, e, 8, 1)
; it pushes the stack pointer itself and an operation id onto the stack before sending
; this is done to include the informaton in the data stream.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Serial_DumpStack:
mov.l r13, @-r15 ; (1)
mov.l r14, @-r15 ; (1A)
sts.l pr, @-r15 ; (2)
mov.l r7, @-r15 ; (3)
mov.l r6, @-r15 ; (4)
mov.l r5, @-r15 ; (5)
mov.l r4, @-r15 ; (6)
mov.l r0, @-r15 ; (6A)
mov.l #SIZE_TO_DUMP, r14
.AIFDEF DUMP_RAM_SIZE
mov.l #DUMP_RAM_SIZE, r5
add r14, r5
.AELSE
mov r14, r5
.AENDI
mov.l r5, @-r15 ; push size to transfer (7)
mov.l r15, @-r15 ; push current stack pointer (7A)
mov.l #h'AA55A5A5, r13
mov.l r13, @-r15 ; push operation id (not currently used by the serial-receiver,
; but included for future use) (8)
; useful while inspecting the buffer
mov r15, r13 ; current stack pointer
add r15, r14
mov r14, r5
bsr innerDumpBuffer
mov r13, r4
.AIFDEF DUMP_RAM_SIZE
mov.l #DUMP_RAM, r13
mov.l #DUMP_RAM_SIZE, r14
add r13, r14
mov r14, r5
bsr innerDumpBuffer
mov r13, r4
.AENDI
ADD #h'C, r15 ; (8+7+7A)
mov.l @r15+, r0 ; (6A)
mov.l @r15+, r4 ; (6)
mov.l @r15+, r5 ; (5)
mov.l @r15+, r6 ; (4)
mov.l @r15+, r7 ; (3)
lds.l @r15+, pr ; (2)
mov.l @r15+, r14 ; (1A)
rts
mov.l @r15+, r13 ; (1)
;;;;;
innerDumpBuffer:
; open serial with 115kBaud, e, 8, 1
mov.l r13, @-r15 ; (1)
mov.l r14, @-r15 ; (1A)
sts.l pr, @-r15 ; (2)
add #-8, r15
mov r4, r13
mov r5, r14
mov r15, r4
mov #0, r0
mov.b r0, @r4
mov.b r0, @(3,r4)
mov.b r0, @(5,r4)
mov #9, r0
mov.b r0, @(1,r4)
mov #2, r0
mov.b r0, @(2,r4)
mov #1, r0
mov.b r0, @(4,r4)
; bra ?exit
; nop
mov.l #syscall_entry, r2
mov.l #scSerialOpen, r0
jsr @r2
nop
mov.l #syscall_entry, r2
mov.l #scSerialDisableInt, r0
jsr @r2
nop
?try_send:
bsr OneSend ; send next stack byte
mov.b @r13, r4
cmp/eq #NO_FIFO_SPACE, r0
bt ?try_send
tst r0, r0
bf ?try_close ; on any other error => quit
add #1, r13
cmp/hi r13, r14
bt ?try_send
?try_close:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; wait for serial ping
mov.l #WAIT_FOR_SERIAL, r3
mov.l @r3, r0
tst r0, r0
bt ?check_serial_2
?check_serial:
mov.l #SCFDR0, r3
mov.w @r3, r0
mov.w #h'001F, r2
and r2, r0
tst r0, r0
bt ?check_serial
mov.l #SCFRDR0, r3
mov.b @r3, r0
mov.b #"A", r2
cmp/eq r2, r0
bt ?exit_serial
mov.b #"B", r2
cmp/eq r2, r0
bf ?check_serial
mov.l #WAIT_FOR_SERIAL, r3
mov #0, r0
mov.l r0, @r3
bra ?exit_serial
nop
?check_serial_2:
mov.l #SCFDR0, r3
mov.w @r3, r0
mov.w #h'001F, r2
and r2, r0
tst r0, r0
bt ?exit_serial
mov.l #SCFRDR0, r3
mov.b @r3, r0
mov.b #"A", r2
cmp/eq r2, r0
bf ?exit_serial
mov.l #WAIT_FOR_SERIAL, r3
mov #1, r0
mov.l r0, @r3
?exit_serial
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
?try_close_loop:
mov.l #syscall_entry, r2
mov.l #scSerialClose, r0
; mov.l #scCommClose, r0
jsr @r2
mov.b #wait_for_pending_transmissions, r4
cmp/eq #transmissions_pending, r0
bt ?try_close_loop
try_close_loop_exit:
add #8, r15
lds.l @r15+, pr ; (2)
mov.l @r15+, r14 ; (1A)
rts
mov.l @r15+, r13 ; (1)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; the routine sends any memory range to the serial interface (115kBaud, e, 8, 1)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Serial_DumpBuffer:
sts.l pr, @-r15 ; (2)
bsr innerDumpBuffer
lds.l @r15+, pr ; (2)
rts
nop
OneSend:
mov.l #syscall_entry, r2
mov.l #scSerialTransmitOne, r0
jmp @r2
nop
fxCG_Syscall:
mov.l #SYSCALL_ENTRY, r2
jmp @r2
nop
;;;;; ( void*addr, int count )
innerDumpBufferX:
mov.l r14, @-r15 ; (1)
mov.l r13, @-r15 ; (1A)
sts.l pr, @-r15 ; (2)
mov.l r12, @-r15 ; (2A)
mov.l r11, @-r15 ; (2B)
mov.l r10, @-r15 ; (2C)
mov.l r9, @-r15 ; (2D)
mov r4, r10
mov r5, r11
mov.l #h'88030000-4, r14
mov.l @r14, r9
tst r9, r9
add #-1, r9
mov.l r9, @r14
bf ?memcpy_skip
mov.l #h'88030000, r14
?memcpy_RAM:
mov.l @r10, r12
mov.l r12, @r14
add #4, r10
cmp/hi r10, r11
bt/s ?memcpy_RAM
add #4, r14
; mov.l r10, @r14
; add #4, r14
; mov.l r11, @r14
; add #4, r14
; mov.l r14, @r14
?memcpy_skip:
mov.l @r15+, r9 ; (2D)
mov.l @r15+, r10 ; (2C)
mov.l @r15+, r11 ; (2B)
mov.l @r15+, r12 ; (2A)
lds.l @r15+, pr ; (2)
mov.l @r15+, r13 ; (1A)
rts
mov.l @r15+, r14 ; (1)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; EXPERIMENTAL REDIRECTION FUNCTION
; the routine sends the stack to memory block 0x8803C000.
; This memory range is part of MCS, so check that it is actually not used.
; Sometimes useful in connection with an user-break-exception handler.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.AIF "OS" EQ "fx9860"
RAM_DumpStack:
mov r15, r5 ; memcpy source
mov.l r13, @-r15 ; (1)
mov.l r14, @-r15 ; (1A)
sts.l pr, @-r15 ; (2)
mov.l #h'88040000, r4 ; upper limit of system RAM (starting at 88030000)
mov.l #h'88024000, r6 ; stack upper limit
sub r5, r6 ; length of used stack
sub r6, r4 ; start address in stack sdadow area (target)
mov.l #h'8803C000, r1 ; stack shadow lower limit, normally never reached
mov.l #syscall_entry, r2
mov.l #scMemCpy, r0
jsr @r2 ; syscall
mov.l r4, @r1 ; save the current stack shadow top
lds.l @r15+, pr ; (2)
mov.l @r15+, r14 ; (1A)
rts
mov.l @r15+, r13 ; (1)
.POOL
.AENDI
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; EXPERIMENTAL REDIRECTION FUNCTION
; the routine displays regsiters of interest and waits.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;DisplayRegisters:
;; mov.l r13, @-r15
;; mov.l r14, @-r15
;; sts.l pr, @-r15
;;
;; mov.l #debug_stack, r2
;; jsr @r2
;; mov #h'2c, r4
;;
;; lds.l @r15+, pr
;; mov.l @r15+, r14
;; rts
;; mov.l @r15+, r13
.POOL
; DEBUG DISPLAY
;
; bsr display_int_as_hex
; mov r12, r4
; bsr display_int_as_hex
; mov r13, r4
; bra ?return
; nop
;
; DEBUG DISPLAY
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; direct draw a pattern to the display
; used as debug aid. si 11.6.2009
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DrawPattern:
sts.l pr, @-r15
.AIF "DRAW_WHAT" EQ "PATTERN"
mov #32, r5
mov #h'FF, r6
bsr WriteToPage
mov #7, r4
mov #33, r5
mov #h'FF, r6
bsr WriteToPage
mov #7, r4
mov #34, r5
mov #h'FF, r6
bsr WriteToPage
mov #7, r4
.AELSE
bsr Bdisp_PutDisp_DD
nop
.AENDI
.AIF "DRAW_WITH_DELAY" EQ "TRUE"
mov.l #10000000, r4
?loop:
dt r4
bf ?loop
.AENDI
lds.l @r15+, pr
RTS
NOP
.POOL
WriteToPage:
mov #4, r3
mov.l #h'B4010000, r7
mov #7, r1
mov.l #h'B4000000, r0
mov.b r3, @r0
mov.w #h'C0, r2
or r2, r5
mov.b r5, @r7 ; reg4 : X (0..19)
mov.b r3, @r0
mov.b r4, @r7 ; reg4 : Y (0..63)
mov.b r1, @r0
rts
mov.b r6, @r7 ; reg7:DATA
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Bdisp_PutDisp_DD:
mov.l #syscall_entry, r2
mov.l #scBdisp_PutDisp_DD, r0
jmp @r2
nop
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; display_int_as_hex in a box
; r4 is the integer to display
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.AIF "OS" EQ "fx9860"
display_int_as_hex:
sts.l pr, @-r15 ; push pr
add #-h'C, r15 ; reserve some stack as working buffer
mov.l #syscall_entry, r2
mov.l #scLongToAscHex, r0
mov r15, r5 ; buffer
jsr @r2
mov #8, r6 ; digits
; draw a box
mov.l #syscall_entry, r2
mov.l #scDispBox, r0
jsr @r2
mov #3, r4 ; count of lines
; locate the cursor
mov #3, r5 ; row
bsr locate
mov #4, r4 ; column
; print a message
mov.l r15, r4
bsr Print
nop
; wait for any key
mov.l #syscall_entry, r2
mov.l #scGetKey, r0
jsr @r2
mov r15, r4
add #h'C, r15 ; restore stack
lds.l @r15+, pr ; pop pr
rts
nop
.POOL
.AENDI
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; EXPERIMENTAL REDIRECTION FUNCTION
; Display something
; this is a demonstration of how to display a messagebox and wait for any key
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.AIF "OS" EQ "fx9860"
display_some:
mov.l r13, @-r15 ; push r13
sts.l pr, @-r15 ; push pr
add #-h'4, r15 ; reserve some stack as return buffer for getkey
bra ?label1
nop
mov.l #syscall_entry, r2
mov.l #scDispError, r0
jsr @r2
mov #2, r4
bra ?return
nop
?label1:
; draw a box
mov.l #syscall_entry, r2
mov.l #scDispBox, r0
jsr @r2
mov #5, r4 ; count of lines
; locate the cursor
mov #3, r5 ; row
bsr locate
mov #4, r4 ; column
; print a message
mov.l #TestMessage1, r4
bsr Print
nop
; locate the cursor
mov #5, r5 ; row
bsr locate
mov #5, r4 ; column
; print a message
mov.l #TestMessage2, r4
bsr Print
nop
; wait for any key
mov.l #syscall_entry, r2
mov.l #scGetKey, r0
jsr @r2
mov r15, r4
?return:
add #h'4, r15 ; adjust the stack pointer
lds.l @r15+, pr ; pop pr
rts
mov.l @r15+, r13 ; pop r13
Print:
sts.l pr, @-r15 ; push pr
mov.l #syscall_entry, r2
mov.l #scPrint, r0
jsr @r2
nop
lds.l @r15+, pr ; pop pr
rts
nop
locate:
sts.l pr, @-r15 ; push pr
mov.l #syscall_entry, r2
mov.l #scLocate, r0
jsr @r2
nop
lds.l @r15+, pr ; pop pr
rts
nop
.POOL
.AENDI
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; "unused"-dummy
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
unused_fno:
rts
nop
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; return a pointer to a ASCIZZ string list,
; which first two strings are displayed by INSIGHT after install
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GetRunLibIDPtr:
mov.l #RunLibID, r0
rts
nop
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GetDBR:
stc DBR, r0
rts
nop
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; this routine is a callback by INSIGHT after RunLib installation
; if it returns 0, INSIGHT does nothing
; if it returns bit 0 set (0x01), INSIGHT appends a file,
; which name's pointer has to be returned in r4
; (the files start and length is stored in the RunLib information block
; starting at #h'801FFFE0)
; if it returns bit 1 set (0x02), INSIGHT autoinstalls an experimental exception/interrupt hook
; (see below)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PostInstallation:
mov #0, r0 ; install none
.AIF "REDIRECT_EXCINT" EQ "1"
or #2, r0
.AENDI
rts
nop
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; void SetInterruptHandler( int intno, void*handler );
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SetInterruptHandler:
mov.l #RAM_INTERRUPT_TABLE, r2
shll2 r4
add r2, r4
mov.l @r4, r1
rts
mov.l r5, @r4
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; int GetInterruptHandler( int intno, void*handler );
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GetInterruptHandler:
mov.l #RAM_INTERRUPT_TABLE, r2
shll2 r4
add r2, r4
rts
mov.l @r4, r0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; int GetTableStart( void );
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GetTableStart:
mov.l #TableStart, r0
rts
nop
; .include "fxCG_display.src"
; .include "fxCG_DEBUG.src"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.SECTION C,DATA,ALIGN=4
RunLibID:
.AIF "OS" EQ "fx9860"
.SDATAZ "UBC fx9860 SH-4 RTL"
.AENDI
.AIF "OS" EQ "fxCG"
.SDATAZ "UBC fxCG RTL"
.AENDI
.include "RunLib_version.inc"
.include "datetime.inc"
.SDATAZ ""
TestMessage1:
.SDATAZ "Redirection OK!"
TestMessage2:
.SDATAZ " Congrats!"
.END