From 33613a85afc4b1481367fbe92a17ee59c240250b Mon Sep 17 00:00:00 2001 From: Sven Eisenhauer Date: Fri, 10 Nov 2023 15:11:48 +0100 Subject: add new repo --- .../ARM202U/EXAMPLES/BASICASM/EXAMPLE.APJ | Bin 0 -> 81 bytes .../ARM202U/EXAMPLES/BASICASM/EXAMPLE.S | 14 + .../ARM202U/EXAMPLES/BASICASM/GCD1.APJ | Bin 0 -> 78 bytes .../ARM202U/EXAMPLES/BASICASM/GCD1.S | 21 + .../ARM202U/EXAMPLES/BASICASM/GCD2.APJ | Bin 0 -> 78 bytes .../ARM202U/EXAMPLES/BASICASM/GCD2.S | 17 + .../ARM202U/EXAMPLES/BASICASM/JUMP.APJ | Bin 0 -> 78 bytes .../ARM202U/EXAMPLES/BASICASM/JUMP.S | 40 + .../ARM202U/EXAMPLES/BASICASM/LOADCON1.APJ | Bin 0 -> 82 bytes .../ARM202U/EXAMPLES/BASICASM/LOADCON1.S | 15 + .../ARM202U/EXAMPLES/BASICASM/LOADCON2.APJ | Bin 0 -> 82 bytes .../ARM202U/EXAMPLES/BASICASM/LOADCON2.S | 26 + .../ARM202U/EXAMPLES/BASICASM/LOADCON3.APJ | Bin 0 -> 82 bytes .../ARM202U/EXAMPLES/BASICASM/LOADCON3.S | 14 + .../ARM202U/EXAMPLES/BASICASM/LOADCON4.APJ | Bin 0 -> 82 bytes .../ARM202U/EXAMPLES/BASICASM/LOADCON4.S | 29 + .../ARM202U/EXAMPLES/BASICASM/STRCOPY1.APJ | Bin 0 -> 88 bytes .../ARM202U/EXAMPLES/BASICASM/STRCOPY1.S | 20 + .../ARM202U/EXAMPLES/BASICASM/STRCOPY2.APJ | Bin 0 -> 82 bytes .../ARM202U/EXAMPLES/BASICASM/STRCOPY2.S | 20 + .../ARM202U/EXAMPLES/CANDASM/ADD64_1.C | 10 + .../ARM202U/EXAMPLES/CANDASM/ADD64_2.C | 7 + .../ARM202U/EXAMPLES/CANDASM/ADD64_3.S | 22 + .../ARM202U/EXAMPLES/CANDASM/HALF_STR.C | 10 + .../ARM202U/EXAMPLES/CANDASM/INT64.H | 9 + .../ARM202U/EXAMPLES/CANDASM/MUL64.H | 4 + .../ARM202U/EXAMPLES/CANDASM/MUL64.S | 26 + .../ARM202U/EXAMPLES/CANDASM/MULTEST.APJ | Bin 0 -> 103 bytes .../ARM202U/EXAMPLES/CANDASM/MULTEST.C | 20 + .../ARM202U/EXAMPLES/CANDASM/TWO_CH.C | 9 + .../ARM202U/EXAMPLES/CLSTAND/ERRTEST.C | 86 +++ .../ARM202U/EXAMPLES/CLSTAND/FPESTUB.S | 96 +++ .../ARM202U/EXAMPLES/CLSTAND/MEMMOVE.C | 23 + .../ARM202U/EXAMPLES/CLSTAND/MEMMOVE.H | 3 + .../ARM202U/EXAMPLES/CLSTAND/MEMTEST.C | 89 +++ .../ARM202U/EXAMPLES/CLSTAND/README.TXT | 3 + .../ARM202U/EXAMPLES/CLSTAND/RTSTAND.H | 52 ++ .../ARM202U/EXAMPLES/CLSTAND/RTSTAND.S | 723 ++++++++++++++++++ .../ARM202U/EXAMPLES/CLSTAND/RTSTAND1.H | 56 ++ .../ARM202U/EXAMPLES/CLSTAND/RTSTAND1.S | 787 ++++++++++++++++++++ .../ARM202U/EXAMPLES/CLSTAND/THUMB/RTSTAND.S | 819 +++++++++++++++++++++ .../ARM202U/EXAMPLES/DHRY/ARMSD.MAP | 1 + .../ARM202U/EXAMPLES/DHRY/DHRY.APJ | Bin 0 -> 112 bytes .../ARM202U/EXAMPLES/DHRY/DHRY.H | 431 +++++++++++ .../ARM202U/EXAMPLES/DHRY/DHRY_1.C | 395 ++++++++++ .../ARM202U/EXAMPLES/DHRY/DHRY_2.C | 192 +++++ .../ARM202U/EXAMPLES/EXPLASM/BYTEDEMO.C | 148 ++++ .../ARM202U/EXAMPLES/EXPLASM/DIVC.C | 213 ++++++ .../ARM202U/EXAMPLES/EXPLASM/RANDOM.S | 42 ++ .../ARM202U/EXAMPLES/EXPLASM/RANDTEST.C | 20 + .../ARM202U/EXAMPLES/EXPLASM/RANTEST.APJ | Bin 0 -> 92 bytes .../ARM202U/EXAMPLES/EXPLASM/UDIV10.S | 23 + .../ARM202U/EXAMPLES/EXPLASM/UTOA.APJ | Bin 0 -> 101 bytes .../ARM202U/EXAMPLES/EXPLASM/UTOA1.S | 60 ++ .../ARM202U/EXAMPLES/EXPLASM/UTOATEST.C | 22 + .../ARM202U/EXAMPLES/OVERLAY/GETDATA.C | 17 + .../ARM202U/EXAMPLES/OVERLAY/MAIN.C | 55 ++ .../ARM202U/EXAMPLES/OVERLAY/MAININIT.S | 9 + .../ARM202U/EXAMPLES/OVERLAY/MAKEFILE | 27 + .../ARM202U/EXAMPLES/OVERLAY/OVERMGRS.S | 391 ++++++++++ .../ARM202U/EXAMPLES/OVERLAY/OVLIST | 2 + .../ARM202U/EXAMPLES/OVERLAY/STARTUP.S | 52 ++ .../ARM202U/EXAMPLES/OVERLAY/TEXT.TXT | 742 +++++++++++++++++++ .../ARM202U/EXAMPLES/OVERLAY/UUE.C | 23 + .../ARM202U/EXAMPLES/PROGC/DSPDIV.C | 18 + .../ARM202U/EXAMPLES/REENT/CONFIG.H | 74 ++ .../ARM202U/EXAMPLES/REENT/DYNLINK.S | 72 ++ .../ARM202U/EXAMPLES/REENT/INTERNS.H | 12 + .../ARM202U/EXAMPLES/REENT/MAIN.S | 26 + .../ARM202U/EXAMPLES/REENT/MAKEFILE | 101 +++ .../ARM202U/EXAMPLES/REENT/STRSHL | 34 + .../ARM202U/EXAMPLES/REENT/STRSTUB.APJ | Bin 0 -> 156 bytes .../ARM202U/EXAMPLES/REENT/STRTEST.APJ | Bin 0 -> 103 bytes .../ARM202U/EXAMPLES/REENT/STRTEST.C | 18 + .../ARM202U/EXAMPLES/ROM/EX.C | 52 ++ .../ARM202U/EXAMPLES/ROM/INIT.S | 164 +++++ .../ARM202U/EXAMPLES/ROM/SPRINTF.C | 31 + .../ARM202U/EXAMPLES/SCATTER/ARMSD.OB | 3 + .../ARM202U/EXAMPLES/SCATTER/GETDATA.C | 16 + .../ARM202U/EXAMPLES/SCATTER/INITAPP.S | 81 ++ .../ARM202U/EXAMPLES/SCATTER/MAIN.C | 33 + .../ARM202U/EXAMPLES/SCATTER/MAININIT.S | 12 + .../ARM202U/EXAMPLES/SCATTER/MAKEFILE | 29 + .../ARM202U/EXAMPLES/SCATTER/OVERMGRS.S | 326 ++++++++ .../ARM202U/EXAMPLES/SCATTER/README.TXT | 745 +++++++++++++++++++ .../ARM202U/EXAMPLES/SCATTER/SCATDES | 26 + .../ARM202U/EXAMPLES/SCATTER/SCATTER.APJ | Bin 0 -> 218 bytes .../ARM202U/EXAMPLES/SCATTER/STARTUP.S | 52 ++ .../ARM202U/EXAMPLES/SCATTER/UUE.C | 26 + .../ARM202U/EXAMPLES/SORTS/ARMSD.MAP | 1 + .../ARM202U/EXAMPLES/SORTS/SORTS.C | 135 ++++ .../ARM202U/EXAMPLES/SWI/HANDLE.S | 42 ++ .../ARM202U/EXAMPLES/SWI/INSTALL.C | 105 +++ .../ARM202U/EXAMPLES/SWI/INSTALLH.C | 17 + .../ARM202U/EXAMPLES/SWI/NEWLINE.C | 6 + .../ARM202U/EXAMPLES/SWI/READLINE.C | 9 + .../ARM202U/EXAMPLES/SWI/SWI.APJ | Bin 0 -> 91 bytes .../ARM202U/EXAMPLES/SWI/SWIMANIP.C | 9 + .../ARM202U/EXAMPLES/UNUSED/UNUSED.C | 14 + 99 files changed, 8224 insertions(+) create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/EXAMPLE.APJ create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/EXAMPLE.S create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/GCD1.APJ create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/GCD1.S create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/GCD2.APJ create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/GCD2.S create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/JUMP.APJ create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/JUMP.S create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/LOADCON1.APJ create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/LOADCON1.S create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/LOADCON2.APJ create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/LOADCON2.S create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/LOADCON3.APJ create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/LOADCON3.S create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/LOADCON4.APJ create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/LOADCON4.S create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/STRCOPY1.APJ create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/STRCOPY1.S create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/STRCOPY2.APJ create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/STRCOPY2.S create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/ADD64_1.C create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/ADD64_2.C create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/ADD64_3.S create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/HALF_STR.C create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/INT64.H create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/MUL64.H create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/MUL64.S create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/MULTEST.APJ create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/MULTEST.C create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/TWO_CH.C create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/ERRTEST.C create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/FPESTUB.S create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/MEMMOVE.C create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/MEMMOVE.H create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/MEMTEST.C create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/README.TXT create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/RTSTAND.H create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/RTSTAND.S create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/RTSTAND1.H create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/RTSTAND1.S create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/THUMB/RTSTAND.S create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/DHRY/ARMSD.MAP create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/DHRY/DHRY.APJ create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/DHRY/DHRY.H create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/DHRY/DHRY_1.C create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/DHRY/DHRY_2.C create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/EXPLASM/BYTEDEMO.C create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/EXPLASM/DIVC.C create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/EXPLASM/RANDOM.S create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/EXPLASM/RANDTEST.C create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/EXPLASM/RANTEST.APJ create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/EXPLASM/UDIV10.S create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/EXPLASM/UTOA.APJ create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/EXPLASM/UTOA1.S create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/EXPLASM/UTOATEST.C create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/OVERLAY/GETDATA.C create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/OVERLAY/MAIN.C create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/OVERLAY/MAININIT.S create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/OVERLAY/MAKEFILE create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/OVERLAY/OVERMGRS.S create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/OVERLAY/OVLIST create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/OVERLAY/STARTUP.S create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/OVERLAY/TEXT.TXT create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/OVERLAY/UUE.C create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/PROGC/DSPDIV.C create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/REENT/CONFIG.H create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/REENT/DYNLINK.S create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/REENT/INTERNS.H create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/REENT/MAIN.S create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/REENT/MAKEFILE create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/REENT/STRSHL create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/REENT/STRSTUB.APJ create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/REENT/STRTEST.APJ create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/REENT/STRTEST.C create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/ROM/EX.C create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/ROM/INIT.S create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/ROM/SPRINTF.C create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/ARMSD.OB create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/GETDATA.C create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/INITAPP.S create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/MAIN.C create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/MAININIT.S create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/MAKEFILE create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/OVERMGRS.S create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/README.TXT create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/SCATDES create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/SCATTER.APJ create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/STARTUP.S create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/UUE.C create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SORTS/ARMSD.MAP create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SORTS/SORTS.C create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SWI/HANDLE.S create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SWI/INSTALL.C create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SWI/INSTALLH.C create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SWI/NEWLINE.C create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SWI/READLINE.C create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SWI/SWI.APJ create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SWI/SWIMANIP.C create mode 100644 Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/UNUSED/UNUSED.C (limited to 'Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES') diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/EXAMPLE.APJ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/EXAMPLE.APJ new file mode 100644 index 0000000..ea94b2c Binary files /dev/null and b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/EXAMPLE.APJ differ diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/EXAMPLE.S b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/EXAMPLE.S new file mode 100644 index 0000000..c93e244 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/EXAMPLE.S @@ -0,0 +1,14 @@ + AREA Example, CODE, READONLY ; name this block of code + ENTRY ; mark first instruction + ; to execute +start + MOV r0, #15 ; Set up parameters + MOV r1, #20 + BL firstfunc ; Call subroutine + SWI 0x11 ; terminate + +firstfunc ; Subroutine firstfunc + ADD r0, r0, r1 ; r0 = r0 + r1 + MOV pc, lr ; Return from subroutine + ; with result in r0 + END ; mark end of file diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/GCD1.APJ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/GCD1.APJ new file mode 100644 index 0000000..b2853cb Binary files /dev/null and b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/GCD1.APJ differ diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/GCD1.S b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/GCD1.S new file mode 100644 index 0000000..fec499f --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/GCD1.S @@ -0,0 +1,21 @@ + AREA gcd1, CODE, READONLY ; name this block of code + ENTRY ; mark first instruction + ; to execute +start + MOV r0, #1 ; Set up parameters + MOV r1, #2 + BL gcd ; Call subroutine + SWI 0x11 ; terminate + +gcd + CMP r0, r1 + BEQ end + BLT less + SUB r0, r0, r1 + BAL gcd +less + SUB r1, r1, r0 + BAL gcd +end MOV pc,lr + + END ; mark end of file \ No newline at end of file diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/GCD2.APJ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/GCD2.APJ new file mode 100644 index 0000000..30403da Binary files /dev/null and b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/GCD2.APJ differ diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/GCD2.S b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/GCD2.S new file mode 100644 index 0000000..8fbc660 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/GCD2.S @@ -0,0 +1,17 @@ + AREA gcd2, CODE, READONLY ; name this block of code + ENTRY ; mark first instruction + ; to execute +start + MOV r0, #1 ; Set up parameters + MOV r1, #2 + BL gcd ; Call subroutine + SWI 0x11 ; terminate + +gcd + CMP r0, r1 + SUBGT r0, r0, r1 + SUBLT r1, r1, r0 + BNE gcd + MOV pc,lr + + END ; mark end of file \ No newline at end of file diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/JUMP.APJ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/JUMP.APJ new file mode 100644 index 0000000..7728951 Binary files /dev/null and b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/JUMP.APJ differ diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/JUMP.S b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/JUMP.S new file mode 100644 index 0000000..fbcb4eb --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/JUMP.S @@ -0,0 +1,40 @@ + AREA ArithGate, CODE ; name this block of code + ENTRY ; mark the first instruction to call +main + MOV r0, #2 ; set up three parameters + MOV r1, #5 + MOV r2, #15 + BL arithfunc ; call the function + SWI 0x11 ; terminate + +arithfunc ; label the function + CMP r0, #4 ; Treat code as unsigned integer + BHI ReturnA1 ; If code > 4 then return first + ; argument + ADR r3, JumpTable ; Load address of the jump table + LDR pc,[r3,r0,LSL #2] ; Jump to appropriate routine + +JumpTable + DCD ReturnA1 + DCD ReturnA2 + DCD DoAdd + DCD DoSub + DCD DoRsb + +ReturnA1 + MOV r0, r1 ; Operation 0, >4 + MOV pc,lr +ReturnA2 + MOV r0, r2 ; Operation 1 + MOV pc,lr +DoAdd + ADD r0, r1, r2 ; Operation 2 + MOV pc,lr +DoSub + SUB r0, r1, r2 ; Operation 3 + MOV pc,lr +DoRsb + RSB r0, r1, r2 ; Operation 4 + MOV pc,lr + + END ; mark the end of this file diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/LOADCON1.APJ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/LOADCON1.APJ new file mode 100644 index 0000000..7641f19 Binary files /dev/null and b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/LOADCON1.APJ differ diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/LOADCON1.S b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/LOADCON1.S new file mode 100644 index 0000000..0cfc12a --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/LOADCON1.S @@ -0,0 +1,15 @@ + AREA loadcon1, CODE + ENTRY ; mark first instruction + + MOV r0, #0 ; => MOV r0, #0 + MOV r1, #0xFF000000 ; => MOV r1, #0xFF, 8 + MOV r2, #0xFFFFFFFF ; => MVN r2, #0 + MVN r0, #1 ; => MVN r0, #1 + MOV r1, #0xFC000003 ; => MOV r1, #0xFF, 6 + MOV r2, #0x03FFFFFC ; => MVN r2, #0xFF, 6 + ;MOV r3, #0x55555555 ; Reports an error (it cannot + ; be constructed) + + SWI 0x11 ; terminate + END + diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/LOADCON2.APJ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/LOADCON2.APJ new file mode 100644 index 0000000..08e91df Binary files /dev/null and b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/LOADCON2.APJ differ diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/LOADCON2.S b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/LOADCON2.S new file mode 100644 index 0000000..53deb76 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/LOADCON2.S @@ -0,0 +1,26 @@ + AREA Loadcon2, CODE + ENTRY ; Mark first instruction + BL func1 ; Branch to first subroutine + BL func2 ; Branch to second subroutine + SWI 0x11 ; Terminate +func1 + LDR r0, =42 ; => MOV R0, #42 + LDR r1, =0x55555555 ; => LDR R1, [PC, #offset to Literal + ; Pool 1] + LDR r2, =0xFFFFFFFF ; => MVN R2, #0 + MOV pc, lr + + LTORG ; Literal Pool 1 contains + ; literal &55555555 +func2 + LDR r3, =0x55555555 ; => LDR R3, [PC, #offset to Literal + ; Pool 1] + ; LDR r4, =0x66666666 ; If this is uncommented it will + ; fail, as Literal Pool 2 is not + ; accessible (out of reach) + MOV pc, lr + +LargeTable % 4200 ; Clears a 4200 byte area of memory, + ; starting at the current location, + ; to zero. + END ;Literal Pool 2 is empty diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/LOADCON3.APJ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/LOADCON3.APJ new file mode 100644 index 0000000..4b82261 Binary files /dev/null and b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/LOADCON3.APJ differ diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/LOADCON3.S b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/LOADCON3.S new file mode 100644 index 0000000..425c1de --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/LOADCON3.S @@ -0,0 +1,14 @@ + AREA Example, CODE + ENTRY ; Mark first instruction +Start + ADR r0, Start ; => SUB r0, PC, #offset to Start + ADR r1, DataArea ; => ADD r1, PC, #offset to DataArea + ; ADR r2, DataArea+4300 ; This would fail as the offset is + ; cannot be expressed by operand2 + ; of an ADD + ADRL r3, DataArea+4300 ; => ADD r2, PC, #offset1 + ; ADD r2, r2, #offset2 + SWI 0x11 ; Terminate +DataArea % 8000 + + END diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/LOADCON4.APJ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/LOADCON4.APJ new file mode 100644 index 0000000..575662f Binary files /dev/null and b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/LOADCON4.APJ differ diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/LOADCON4.S b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/LOADCON4.S new file mode 100644 index 0000000..5f046c9 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/LOADCON4.S @@ -0,0 +1,29 @@ + AREA Loadcon4, CODE + ENTRY ; Mark first instruction +Start + BL func1 ; Branch to first subroutine + BL func2 ; Branch to second subroutine + SWI 0x11 ; Terminate + +func1 + LDR r0, =Start ; => LDR R0,[PC, #offset to + ; Litpool 1] + LDR r1, =Darea +12 ; => LDR R1,[PC, #offset to + ; Litpool 1] + LDR r2, =Darea + 6000 ; => LDR R2, [PC, #offset to + ; Litpool 1] + MOV pc,lr ; Return + + LTORG ; Literal Pool 1 contains 3 literals + +func2 + LDR r3, =Darea +6000 ; => LDR r3, [PC, #offset to + ; Litpool 1] + ; (sharing with previous literal) + ; LDR r4, =Darea +6004 ; If uncommented will produce an + ; error as Litpool 2 is out of range + MOV pc, lr ; Return + +Darea % 8000 + END ; Literal Pool 2 is out of range of + ; the LDR instructions above diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/STRCOPY1.APJ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/STRCOPY1.APJ new file mode 100644 index 0000000..1e19af0 Binary files /dev/null and b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/STRCOPY1.APJ differ diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/STRCOPY1.S b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/STRCOPY1.S new file mode 100644 index 0000000..d719799 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/STRCOPY1.S @@ -0,0 +1,20 @@ + AREA StrCopy1, CODE + ENTRY ; mark the first instruction +main + ADR r1, srcstr ; pointer to first string + ADR r0, dststr ; pointer to second string + BL strcopy ; copy the first into second + SWI 0x11 ; and exit + +srcstr DCB "This is my first (source) string",0 +dststr DCB "This is my second (destination) string",0 + + ALIGN ; realign address to word boundary + +strcopy + LDRB r2, [r1], #1 ; load byte, then update address + STRB r2, [r0], #1 ; store byte, then update address + CMP r2, #0 ; check for zero terminator + BNE strcopy ; keep going if not + MOV pc, lr ; return + END diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/STRCOPY2.APJ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/STRCOPY2.APJ new file mode 100644 index 0000000..174fca4 Binary files /dev/null and b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/STRCOPY2.APJ differ diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/STRCOPY2.S b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/STRCOPY2.S new file mode 100644 index 0000000..aa3e954 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/BASICASM/STRCOPY2.S @@ -0,0 +1,20 @@ + AREA StrCopy2, CODE + ENTRY ; mark the first instruction +main + LDR r1, =srcstr ; pointer to first string + LDR r0, =dststr ; pointer to second string + BL strcopy ; copy the first into second + SWI 0x11 ; and exit + +srcstr DCB "This is my first (source) string",0 +dststr DCB "This is my second (destination) string",0 + + ALIGN ; realign address to word boundary + +strcopy + LDRB r2, [r1], #1 ; load byte, then update address + STRB r2, [r0], #1 ; store byte, then update address + CMP r2, #0 ; check for zero terminator + BNE strcopy ; keep going if not + MOV pc, lr ; return + END diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/ADD64_1.C b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/ADD64_1.C new file mode 100644 index 0000000..9a7744f --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/ADD64_1.C @@ -0,0 +1,10 @@ +#include "int64.h" + +void add_64(int64 *dest, int64 *src1, int64 *src2) +{ unsigned hibit1=src1->lo >> 31, hibit2=src2->lo >> 31, hibit3; + dest->lo=src1->lo + src2->lo; + hibit3=dest->lo >> 31; + dest->hi=src1->hi + src2->hi + + ((hibit1 & hibit2) || (hibit1!= hibit3)); + return; +} diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/ADD64_2.C b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/ADD64_2.C new file mode 100644 index 0000000..96735fb --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/ADD64_2.C @@ -0,0 +1,7 @@ +#include "int64.h" + +void add_64(int64 *dest, int64 *src1, int64 *src2) +{ dest->lo=src1->lo + src2->lo; + dest->hi=src1->hi + src2->hi; + return; +} diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/ADD64_3.S b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/ADD64_3.S new file mode 100644 index 0000000..17a0f36 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/ADD64_3.S @@ -0,0 +1,22 @@ +; generated by Norcroft ARM C vsn 4.41 (Advanced RISC Machines) [Aug 26 1992] + + AREA |C$$code|, CODE, READONLY +|x$codeseg| + + EXPORT add_64 +add_64 + LDR a4,[a2,#0] + LDR ip,[a3,#0] + ADDS a4,a4,ip + STR a4,[a1,#0] + LDR a2,[a2,#4] + LDR a3,[a3,#4] + ADC a2,a2,a3 + STR a2,[a1,#4] + MOV pc,lr + + AREA |C$$data|,DATA + +|x$dataseg| + + END diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/HALF_STR.C b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/HALF_STR.C new file mode 100644 index 0000000..0f00e81 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/HALF_STR.C @@ -0,0 +1,10 @@ +typedef struct half_words_struct +{ unsigned field1:16; + unsigned field2:16; +} half_words; + +half_words max( half_words a, half_words b ) +{ half_words x; + x= (a.field1>b.field1) ? a : b; + return x; +} diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/INT64.H b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/INT64.H new file mode 100644 index 0000000..0b017f4 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/INT64.H @@ -0,0 +1,9 @@ +#ifndef __int64_h +#define __int64_h + +typedef struct int64_struct { + unsigned int lo; + unsigned int hi; +} int64; + +#endif diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/MUL64.H b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/MUL64.H new file mode 100644 index 0000000..6d4135e --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/MUL64.H @@ -0,0 +1,4 @@ +/* Declaration of mul64, specifying that the int64 */ +#include "int64.h" + +__value_in_regs extern int64 mul64(unsigned a, unsigned b); diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/MUL64.S b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/MUL64.S new file mode 100644 index 0000000..1b4beb6 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/MUL64.S @@ -0,0 +1,26 @@ +; 32-bit by 32-bit multiplication routine for use with C + + AREA |mul64$$code|, CODE, READONLY + +|x$codeseg| + + EXPORT mul64 + +; On entry a1 and a2 contain the 32-bit integers to be multiplied (a, b) +; On exit a1 and a2 contain the result (a1 bits 0-31, a2 bits 32-63) +mul64 + MOV ip, a1, LSR #16 ; ip = a_hi + MOV a4, a2, LSR #16 ; a4 = b_hi + BIC a1, a1, ip, LSL #16 ; a1 = a_lo + BIC a2, a2, a4, LSL #16 ; a2 = b_lo + MUL a3, a1, a2 ; a3 = a_lo * b_lo (m_lo) + MUL a2, ip, a2 ; a2 = a_hi * b_lo (m_mid1) + MUL a1, a4, a1 ; a1 = a_lo * b_hi (m_mid2) + MUL a4, ip, a4 ; a4 = a_hi * b_hi (m_hi) + ADDS ip, a2, a1 ; ip = m_mid1 + m_mid2 (m_mid) + ADDCS a4, a4, #&10000 ; a4 = m_hi + carry (m_hi') + ADDS a1, a3, ip, LSL #16 ; a1 = m_lo + (m_mid<<16) + ADC a2, a4, ip, LSR #16 ; a2 = m_hi' + (m_mid>>16) + carry + MOV pc, lr + + END diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/MULTEST.APJ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/MULTEST.APJ new file mode 100644 index 0000000..ce0107e Binary files /dev/null and b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/MULTEST.APJ differ diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/MULTEST.C b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/MULTEST.C new file mode 100644 index 0000000..5dc30e6 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/MULTEST.C @@ -0,0 +1,20 @@ +/* Demonstrate mul64 */ + +#include +#include "int64.h" +#include "mul64.h" + +int main() +{ int64 res; + unsigned a,b; + + printf( "Enter two unsigned 32-bit numbers in hex eg.(100 FF43D)\n" ); + if( scanf( "%x %x", &a, &b ) != 2 ) + { puts( "Bad numbers" ); + } else + { res=mul64(a,b); + printf( "Least significant word of result is %8X\n", res.lo ); + printf( "Most significant word of result is %8X\n", res.hi ); + } + return( 0 ); +} diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/TWO_CH.C b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/TWO_CH.C new file mode 100644 index 0000000..9f4c72f --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CANDASM/TWO_CH.C @@ -0,0 +1,9 @@ +typedef struct two_ch_struct +{ char ch1; + char ch2; +} two_ch; + +two_ch max( two_ch a, two_ch b ) +{ + return (a.ch1>b.ch1) ? a : b; +} diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/ERRTEST.C b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/ERRTEST.C new file mode 100644 index 0000000..1315b8f --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/ERRTEST.C @@ -0,0 +1,86 @@ +/* + * Standalone Hello World program - tests for presence of the FP + * support code and also shows how to interface to the + * standalone C kernel's error handler. + * + * Copyright (C) 1993 Advanced RISC Machines Limited. + */ + +#include "rtstand.h" + +extern void __swi(0) put_char(int ch); +extern void __swi(2) put_string(char *string); + +/* First let's roll our own, primitive hex number printer. + * Strictly %#.8X format. + */ +static void puth(unsigned n) { + int j; + put_string("0X"); + for (j = 0; j < 8; ++j) { + put_char("0123456789ABCDEF"[n >> 28]); + n <<= 4; + } +} + +static jmp_buf err_label; + +/* This is the function weakly-referenced from the standalone C kernel. + * If it exists, it will be called when a run-time error occurs. + * If the error is a 'pseudo-error', raised because the error-handler + * has been called directly, then the user's register set *r will contain + * random values for a1-a4 and ip (r[0-3], r[12]) and r[15] will be + * identical to r[14]. + */ +void __err_handler(__rt_error *e, __rt_registers *r) { + put_string("errhandler called: code = "); + puth(e->errnum); + put_string(": "); put_string(e->errmess); put_string("\r\n"); + put_string("caller's pc = "); puth(r->r[15]); + put_string("\r\nreturning...\r\n"); +#ifdef LONGJMP + longjmp(err_label, e->errnum); +#endif +} + +#ifdef DIVIDE_ERROR +#define LIMIT 0 +#else +#define LIMIT 1 +#endif + +int main(int argc, char *argv[]) { + int rc; + + put_string("(the floating point instruction-set is "); + if (!__rt_fpavailable()) put_string("not "); + put_string("available)\r\n"); + +/* Set up the jmp_buffer, and if returning due to longjmp then + * goto errlabel + */ + if ((rc = setjmp(err_label)) != 0) goto errlabel; + + if (__rt_fpavailable()) { + float a; + put_string("Using Floating point, but casting to int ...\r\n"); + for (a=(float) 10.0;a>=(float) LIMIT;a-=(float) 1.0) { + put_string("10000 / "); puth((int) a); put_string(" = "); + puth((int) (10000.0/a)); put_string("\r\n"); + } + } else { + int a; + put_string("Using integer arithmetic ...\r\n"); + for (a=10;a>=LIMIT;a--) { + put_string("10000 / "); puth(a); put_string(" = "); + puth(10000/a); put_string("\r\n"); + } + } + return 0; + +errlabel: + put_string("\nReturning from __err_handler() with errnum = "); + puth(rc); + put_string("\r\n\n"); + return 0; +} diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/FPESTUB.S b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/FPESTUB.S new file mode 100644 index 0000000..f015a18 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/FPESTUB.S @@ -0,0 +1,96 @@ +;;; fpestub.s: library stub for fpe400 (emulator for fp instruction set 3) +;;; +;;; Copyright (C) Advanced RISC Machines Ltd., 1993 + +;;; RCS $Revision: 1.5 $ +;;; Checkin $Date: 1994/01/24 14:19:42 $ +;;; Revising $Author: irickard $ + + AREA |FP$$code|, CODE + + IMPORT __rt_trap, WEAK ; from run-time kernel... + +; change FPE_ to FPS_ to allow FPA support code to be incorporated in library +; (there is currently no veneer support for the combined FPE/FPASC) + IMPORT FPE_Install + IMPORT FPE_DeInstall + EXPORT FPE_GenerateError ; to FPE + + EXPORT __fp_initialise ; to client + EXPORT __fp_finalise ; to client + EXPORT __fp_address_in_emulator ; to client + + IMPORT |FP$$code$$Base| + IMPORT |FP$$code$$Limit| + + +; RISCOS SWI names (for use in very_standalone only). + +Write0 * 2 + (1:SHL:17) +NewLine * 3 + (1:SHL:17) +Exit * &11 + +;****************************************************************************** +; + + +__fp_initialise + B FPE_Install + +__fp_finalise + B FPE_DeInstall + +;****************************************************************************** +; +; Come here for a floating point exception, such as divide by zero. +; +; r0 = error descriptor +; r1 -> cpu register dump +; + +FPE_GenerateError +; still in some non-user mode... + LDR r2, =|__rt_trap| + CMP r2, #0 + BEQ very_standalone + ADD r3, r1, #r13*4 + LDMIA r3, {r13}^ ; retrieve user's sp + NOP + MOVS pc, r2 ; to __rt_ in user mode + + +very_standalone + [ {CONFIG} = 26 + TEQP pc, #0 ; to user mode + | + MSR CPSR_ctl, #&10 ; to user32 + ] + ADD r0, r0, #4 ; ignore the error code + SWI Write0 ; write the message + SWI NewLine + BL |__fp_finalise| ; tidy the ill-instr vector + SWI Exit ; and exit + +|__fp_address_in_emulator| + ; for the benefit of abort handling, determine whether an address + ; is within the code of the fp emulator. (Allowing a data abort or + ; address exception in a floating-point load or store to be reported + ; as occurring at that instruction, rather than somewhere in the code + ; of the emulator). + [ {CONFIG} = 26 + BIC r0, r0, #&fc000003 ; remove PSR bits in case + ] + LDR r1, =|FP$$code$$Base| + CMP r0, r1 + LDRGT r1, =|FP$$code$$Limit| + CMPGT r1, r0 + MOVLE r0, #0 + MOVGT r0, #1 + [ {CONFIG} = 26 + MOVS pc, lr + | + MOV pc, lr + ] + LTORG + + END diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/MEMMOVE.C b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/MEMMOVE.C new file mode 100644 index 0000000..8039f11 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/MEMMOVE.C @@ -0,0 +1,23 @@ +#include "memmove.h" + +void *__rt_memmove(void *a, const void *b, size_t n) +/* copy memory taking care of overlap */ +/* Relies on sizeof(int)=sizeof(void *) and byte addressing. + Also that memory does not wrap round for direction test. */ +{ + /* do it fast if word aligned ... */ + if ((((int)a | (int)b | (int)n) & 3) == 0) + { int *wa,*wb; + n >>= 2; + if (a < (void *)b) + for (wa = (int *)a, wb = (int *)b; n-- > 0;) *wa++ = *wb++; + else for (wa = n+(int *)a, wb = n+(int *)b; n-- > 0;) *--wa = *--wb; + } + else + { char *ca,*cb; + if (a < (void *)b) + for (ca = (char *)a, cb = (char *)b; n-- > 0;) *ca++ = *cb++; + else for (ca = n+(char *)a, cb = n+(char *)b; n-- > 0;) *--ca = *--cb; + } + return a; +} diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/MEMMOVE.H b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/MEMMOVE.H new file mode 100644 index 0000000..480df1b --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/MEMMOVE.H @@ -0,0 +1,3 @@ +typedef unsigned int size_t; /* others (e.g. ) define */ + +extern void *__rt_memmove(void * /*s1*/, const void * /*s2*/, size_t /*n*/); diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/MEMTEST.C b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/MEMTEST.C new file mode 100644 index 0000000..46e8f1a --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/MEMTEST.C @@ -0,0 +1,89 @@ +/* + * Standalone run-time system test. + * + * This program checks that stack overflow checking works and that it + * interacts properly with heap extension. + * + * Copyright (C) 1991 Advanced RISC Machines Limited. + */ + +#include "rtstand.h" + +extern void __swi(0) put_char(int ch); +extern void __swi(2) put_string(char *string); + +/* First, we make a function to claim a large(-ish) stack frame. + * Some obfuscation in case the compiler optimises us away... + */ +static int stack(int n, int v) { + /* claim n KB of stack */ + int x[256],i; + + if (n > 1) v = stack(n-1, v); + for (i = 0; i < 256; ++i) x[i] = v + i; + return x[0] + x[255]; +} + +/* Now we roll our own decimal output function - strictly %d format... + */ +static void puti(int n) { + if (n < 0) { + put_char('-'); + n = -n; + } + if (n > 9) { + int n1 = n / 10; + n = n % 10; + puti(n1); + } + put_char(n + '0'); +} + +/* ...and a hex outputter... strictly %#.8X format. + */ +static void puth(unsigned n) { + int j; + put_string("0X"); + for (j = 0; j < 8; ++j) { + put_char("0123456789ABCDEF"[n >> 28]); + n <<= 4; + } +} + +/* Finally, we sit in a loop extending the heap and claiming ever bigger + * stack franes until something gives. Probably, the heap will give first, + * as currently tuned, and the program will announce "memory exhausted". + * If you tune it differently, it can be made to fail will a stack overflow + * run-time error. Try compiling this -DSTACK_OVERFLOW to provoke it. + */ +int main(int argc, char *argv[]) { + unsigned size, ask, got, total; + void *base; + + put_string("kernel memory management test\r\n"); + + size = 4; /* KB */ + ask = 0; + for (total = 0;;) { + put_string("force stack to "); puti(size); put_string("KB\r\n"); + stack(size, 0); + put_string("request "); puti(ask); put_string(" words of heap - "); + got = __rt_alloc(ask, &base); + total += got; + put_string("allocate "); puti(got); + put_string(" words at "); puth((unsigned)base); put_string("\r\n"); + if (got < ask) break; + ask += got / 2; +#ifdef STACK_OVERFLOW + size *= 2; +#else + size += 4; +#endif + } + + put_string("memory exhausted, "); + puti(total); put_string(" words of heap, "); + puti(size); put_string("KB of stack\r\n"); + + return 0; +} diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/README.TXT b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/README.TXT new file mode 100644 index 0000000..bc81770 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/README.TXT @@ -0,0 +1,3 @@ +For details of how to use the files in this directory refer to the ARM +Programming Techniques, and in particular to the section on +Deeply Embedded Programming in C. diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/RTSTAND.H b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/RTSTAND.H new file mode 100644 index 0000000..1b956ea --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/RTSTAND.H @@ -0,0 +1,52 @@ +/* + * Standalone C run-time kernel. + * Copyright (C) 1991 Advanced RISC Machines Limited. + */ + +#ifndef __rtstand_h +#define __rtstand_h + + +extern void __rt_exit(int /* code */); /* + * Terminate execution; equivalent to returning from main. + * NOTE: all other details are determined by your implementation. + */ + +typedef struct {unsigned errnum; char errmess[252];} __rt_error; +typedef struct {int r[16];} __rt_registers; + +extern void __err_handler(__rt_error *, __rt_registers *); + +extern int __rt_fpavailable(void); +/* + * Return non-0 iff there is support for the floating-point instruction set. + */ + +extern unsigned __rt_alloc(unsigned /*minwords*/, void ** /*block*/); +/* + * Tries to allocate a block of sensible size >= minwords. Failing that, + * it allocates the largest possible block (may have size zero). + * Sensible size is determined by your implementation (default: 256 words). + * *block is set to a pointer to the start of the allocated block + * (NULL if 'a block of size zero' has been allocated). + */ + +#ifdef __JMP_BUF_SIZE +typedef int jmp_buf[__JMP_BUF_SIZE]; +#else +typedef int jmp_buf[22]; /* size suitable for the ARM */ +#endif /* an array type suitable for holding the data */ + /* needed to restore a calling environment. */ +#ifdef __STDC__ +/* setjmp is a macro so that it cannot be used other than directly called. */ +/* NB that ANSI declare that anyone who undefined the setjmp macro or uses */ +/* (or defines) the name setjmp without including this header will get */ +/* what they deserve. NOTE: -pcc mode doesn't allow circular definitions...*/ +#define setjmp(jmp_buf) (setjmp(jmp_buf)) +#endif + +extern int setjmp(jmp_buf /*env*/); + +extern int longjmp(jmp_buf /*env*/, int /*val*/); + +#endif diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/RTSTAND.S b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/RTSTAND.S new file mode 100644 index 0000000..325b494 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/RTSTAND.S @@ -0,0 +1,723 @@ +; Issue: 0.03/23-Feb-93 +; +; Purpose: Minimal, standalone, C-library kernel. +; +; Copyright (C) 1993 Advanced RISC Machines Limited. All rights reserved. +; +; Advanced RISC Machines Limited does not assume any liability arising out +; of this program or use thereof neither does it convey any licence under +; its intellectual property rights. +; +; Conditions of use: +; +; The terms and conditions under which this software is supplied to you and +; under which you may use it are described in your licence agreement with +; your supplier. +; +;----------------------------------------------------------------------------; +; ABOUT THIS CODE ; +; ; +; This code shows you how to write your own minimal, standalone, run-time ; +; support system for code compiled by Advanced RISC Machines's C Compiler. ; +; It can be assembled using Advanced RISC Machines's ARM assembler (armasm) ; +; or any assembler comaptible with it. ; +; ; +; This example code has been written to run under Advanced RISC Machines's ; +; ARM emulation system (ARMulator). It can also run without modification ; +; under Acorm Computer's "RISC OS" operating system for its ARM-based ; +; personal workstations. ; +; ; +; In fact, this code depends hardly at all on its target environment and is ; +; designed to be very easy to adapt to your particular ARM-based system. ; +; You can expect it to take about a couple of hours to re-target. ; +; ; +; Much of the code below is generic to the ARM processor and is completely ; +; independent of your ARM-based hardware or any operating system kernel that ; +; may run on it. To get going, you need write only 4 simple fns. ; +; ; +; WHAT THIS CODE PROVIDES: ; +; ; +; - Example, executable implementations (for the ARMulator) of the few ; +; simple functions you need to implement to customise this code to your ; +; environment. These include: ; +; - setting up the initial stack and heap and calling main (__main) ; +; - program termination (__rt_exit) ; +; - determining FP instruction-set availability (__rt_fpavailable) ; +; ; +; - Functions to help with heap allocation, stack-limit checking, setjmp ; +; and longjmp. These may need to be customised for your environment, ; +; but can almost certainly be used as-is in a first re-targetting. ; +; ; +; - Fully 'rolled' divide (and remainder) functions. ; +; ; +; WHAT THIS CODE DOES NOT PROVIDE ; +; ; +; - Support for handling traps, faults, escapes, exceptions or interrupts. ; +; ; +; - A way to print to the debugging channel (use in line SWIs) ; +; ; +;----------------------------------------------------------------------------; + +;----------------------------------------------------------------------------; +; The following constant is the Top Of Memory - Adjust this for your system ; +;----------------------------------------------------------------------------; + +TopOfMemory EQU 0x80000 ; 512Kb + +;----------------------------------------------------------------------------; +; Things you may wish to tune, but which you don't need to alter, follow. ; +;----------------------------------------------------------------------------; + +DefaultStackSize EQU 4*1024 ; The stack starts of this big unless + ; over-ridden by __root_stack_size. + +DefaultStackIncrement EQU 1*1024 ; At each overflow it grows by at + ; at least this many bytes. + +StackSlop EQU 512 ; sl is kept this far above the real + ; stack low-water mark. NOTE: MUST be + ; >= 256 or the compiled limit checks + ; will be invalidated. + +MinHeapIncrement EQU 256 ; Min number of WORDS to extend the + ; heap by on calling __rt_alloc. + + GBLL EnsureNoFPSupport +EnsureNoFPSupport SETL {FALSE} ; If {TRUE} then the availability of + ; Floating Point Support is ignored. + ; If {FALSE} then FP availability is + ; checked for. + ; Setting to {TRUE} saves a little + ; space. + +;----------------------------------------------------------------------------; +; Symbols defined in other, separately-assembled modules, must be IMPORTed. ; +; We import them WEAKly so that they need not be defined. ; +;----------------------------------------------------------------------------; + + IF EnsureNoFPSupport = {FALSE} + IMPORT |__fp_initialise|, WEAK + IMPORT |__fp_finalise|, WEAK + ENDIF + +;----------------------------------------------------------------------------; +; The existence of __fp_initialise (imported WEAKly) indicates that floating ; +; point support code (or the access stub thereof) has been linked with this ; +; application. If you wish to load the FP support code separately, you may ; +; want to define some other mechanism for detecting the presence/absence of ; +; floating point support. Note that setjmp and longjmp must know whether the ; +; floating-point instruction set is supported. ; +; __fp_initialise is called by __main and __fp_finalise is called by _exit. ; +;----------------------------------------------------------------------------; + + IMPORT |__root_stack_size|, WEAK + +;----------------------------------------------------------------------------; +; If __root_stack_size, also imported WEAKly, exists, the value it addresses ; +; is used as the initial size of the stack. It can be defined in your C ; +; program as, e.g. int __root_stack_size = 10000; /* 10KB initial stack */ ; +;----------------------------------------------------------------------------; + + IMPORT |__err_handler|, WEAK + +;----------------------------------------------------------------------------; +; If __err_handler exists, errors are passed to it; otherwise, we print a ; +; simple diagnostic message and exit. ; +;----------------------------------------------------------------------------; + + IMPORT |Image$$RW$$Limit| + +;----------------------------------------------------------------------------; +; Image$$RW$$Limit is a linker-created symbol marking the end of the image. ; +; Its value is used as the heap base. ; +;----------------------------------------------------------------------------; + + IMPORT main + +;----------------------------------------------------------------------------; +; The symbol main identifies the C function entered from this code. ; +;----------------------------------------------------------------------------; + +;----------------------------------------------------------------------------; +; THE MEMORY MODEL ASSUMED BY THIS IMPLEMENTATION ; +; ; +; +----------------+ <--- top of memory (high address) ; +; | Stack space | ; +; |................| <--- stack pointer (sp) ; +; | Free stack | ; +; |................| <--- stack limit pointer (sl) ; +; +----------------+ <--- stack low-water mark (sl - StackSlop) ; +; | | ; +; | Unused memory | ; +; | | ; +; +----------------+ <--- top of heap (HeapLimit) ; +; | | ; +; | Heap space | ; +; | | ; +; +----------------+ <--- top of application (Image$$RW$$Limit) ; +; | Static data | } ; +; |................| } the application's memory image ; +; | Code | } ; +; +----------------+ <--- application load address ; +;----------------------------------------------------------------------------; + +;----------------------------------------------------------------------------; +; Now the symbols we define and EXPORT from this this module. ; +;----------------------------------------------------------------------------; +; First, symbols identifying the four functions you have to implement to ; +; make this run-time kernel work on your hardware. ; +;----------------------------------------------------------------------------; + + EXPORT |__main| + EXPORT |__rt_exit| + EXPORT |__rt_fpavailable| + EXPORT |__rt_trap| + +;----------------------------------------------------------------------------; +; Then some simple support for C heap management. It interacts with stack- ; +; limit checking but should require no attention in a first re-targetting. ; +;----------------------------------------------------------------------------; + + EXPORT |__rt_alloc| + +;----------------------------------------------------------------------------; +; Next, optional support for C stack-limit checking. This code should need ; +; no attention in a first re-targetting. ; +;----------------------------------------------------------------------------; + + EXPORT |__rt_stkovf_split_small| ; veneer + EXPORT |__rt_stkovf_split_big| + +;----------------------------------------------------------------------------; +; Then two C-specific functions which should require no attention in a first ; +; re-targetting. Note that they depend on __rt_fpavailable. ; +;----------------------------------------------------------------------------; + + EXPORT |setjmp| + EXPORT |longjmp| + +;----------------------------------------------------------------------------; +; And, finally, generic ARM functions, referred to by the C compiler. ; +; You should not need to alter any of these unless you wish to incorporate ; +; them in your operating system kernel. See also later comments. ; +;----------------------------------------------------------------------------; + + EXPORT |__rt_udiv| + EXPORT |__rt_udiv10| + EXPORT |__rt_sdiv| + EXPORT |__rt_sdiv10| + EXPORT |__rt_divtest| + +;----------------------------------------------------------------------------; + AREA |C$$data| ; This module's data area ; +;----------------------------------------------------------------------------; + +HeapLimit + DCD |Image$$RW$$Limit| ; initialised by the linker. + +;----------------------------------------------------------------------------; +; This code has to run in but 26-bit ARM modes and 32-bit modes. To allow ; +; for this, the code is carefully written so that all PSR restoration in ; +; 26-bit mode is via the following macro. ; +;----------------------------------------------------------------------------; + + MACRO + RET $cond + IF {CONFIG} = 26 + MOV$cond.S pc, lr + ELSE + MOV$cond pc, lr + ENDIF + MEND + +;----------------------------------------------------------------------------; +; The following four SWI definitions are specific to ARMulator/RISC OS. ; +; However, you will need to replace the whole of this following section... ; +; and all uses of these SWIs should also be replaced. ; +;----------------------------------------------------------------------------; + +WriteC EQU 0 ; Write r0 to error/debug stream. +Write0 EQU 2 ; Write 0-terminated string pointed + ; to by r0 to error/debug stream. +Exit EQU 17 ; Terminate program execution. + +;----------------------------------------------------------------------------; + AREA |C$$code$$__main|, CODE, READONLY +; The code area containing __main, __rt_exit ; +;----------------------------------------------------------------------------; + + ENTRY ; Define the image entry point. + +|__main| +; +; This is the initial entry point to the image. +; Have to establish a stack for C +; No arguments are passed to main from an embedded application, +; so argc and argv are set up to 0 + + MOV sp, #TopOfMemory ; Initial stack pointer... + MOV fp, #0 ; No previous frame, so fp=0 + + LDR a3, RootStackSize + CMP a3, #0 ; Is RootStackSize defined? + LDRNE a3, [a3] ; Yes: use value... + CMPNE a3, #DefaultStackSize ; but check caller not being silly. + MOVLE a3, #DefaultStackSize ; No/silly: use default size. + + SUB sl, sp, a3 ; stack low-water mark + ADD sl, sl, #StackSlop ; sl = LWM + StackSlop + + IF EnsureNoFPSupport = {FALSE} + LDR a1, fp_initialise ; initialise FP code if present + CMP a1, #0 + MOVNE lr, pc + MOVNE pc, a1 + ENDIF + + MOV a1, #0 ; set argc to 0 + MOV a2, #0 ; and argv to NUL + BL main ; Call main, falling through to + ; exit on return. + +|__rt_exit| ; exit +; +; void __rt_exit(int code); +; Terminate execution, optionally setting return code (ignored here). +; MUST NOT RETURN. + + IF EnsureNoFPSupport = {FALSE} + LDR a2, fp_finalise ; finalise FP code if present + CMP a2, #0 + MOVNE lr, pc + MOVNE pc, a2 + ENDIF + SWI Exit ; suicide... + +RootStackSize + DCD |__root_stack_size| + + IF EnsureNoFPSupport = {FALSE} +fp_initialise + DCD |__fp_initialise| +fp_finalise + DCD |__fp_finalise| + ENDIF + +;----------------------------------------------------------------------------; + AREA |C$$code$$__rt_fpavailable|, CODE, READONLY +; The code area containing __rt_fpavailable ; +;----------------------------------------------------------------------------; + +|__rt_fpavailable| +; +; int __rt_fpavailable(); return non-0 if FP support code linked. + + IF EnsureNoFPSupport = {FALSE} + LDR a1, fp_initialise + ELSE + MOV a1, #0 + ENDIF + RET + +;----------------------------------------------------------------------------; + AREA |C$$code$$__rt_trap|, CODE, READONLY +; The code area containing __rt_trap ; +;----------------------------------------------------------------------------; +; Support for low-level failures - currently stack overflow, divide by 0 and ; +; floating-point exceptions. If there is a higher level handler, call it; ; +; otherwise, print a message and exit gracefully. ; +; ; +; NOTES ; +; ; +; typedef struct { unsigned code; char message[252];} __rt_error; ; +; typedef struct { unsigned r[16];} __rt_registers; ; +; ; +;----------------------------------------------------------------------------; + +|__rt_trap| +; +; void __rt_trap(__rt_error *e, __rt_registers *r); + + STMFD sp!, {a1} ; save e in case handler returns... + LDR ip, err_handler + CMP ip, #0 + MOVNE lr, pc + IF {CONFIG} = 26 + MOVNES pc, ip ; if got a handler, use it and + ELSE + MOVNE pc, ip ; if got a handler, use it and + ENDIF + LDMFD sp!, {v1} ; hope not to return... + + ADR a1, RTErrorHead + SWI Write0 ; write preamble... + ADD a1, v1, #4 + SWI Write0 ; write error diagnosis + ADR a1, RTErrorTail + SWI Write0 ; write postlude + MOV a1, #255 + B |__rt_exit| ; and terminate with non-zero exit code +err_handler + DCD |__err_handler| + +save_regs_and_trap + STMFD sp!, {sp, lr, pc} + STMFD sp!, {r0-r12} + STR lr, [sp, #4*15] ; caller's pc is my lr + MOV a2, sp + MOV a1, ip + B |__rt_trap| + +RTErrorHead + DCB 10, 13, "run time error: ", 0 + +RTErrorTail + DCB 10, 13, "program terminated", 10, 13, 10, 13, 0 + + ALIGN + +;----------------------------------------------------------------------------; +; YOU SHOULDN'T NEED TO ALTER ANY OF THE FOLLOWING IN A FIRST RETARGETTING. ; +;----------------------------------------------------------------------------; + +;----------------------------------------------------------------------------; + AREA |C$$code$$__rt_alloc|, CODE, READONLY +; The code area containing __rt_alloc ; +;----------------------------------------------------------------------------; +; Primitive support for heap memory management. ; +; ; +; NOTES ; +; ; +; 1/ The allocator embeds knowledge of the memory layout and interacts with ; +; the stack limit checking code. Here we assume a single address space ; +; with the stack at the top growing down and the heap below it growing ; +; up, with a gap (free memory) in between. ; +; ; +; 2/ Failure of the stack-limit check is fatal. However, failure of the low- ; +; level heap allocator is passed back to its caller. ; +;----------------------------------------------------------------------------; + + +|__rt_alloc| ; alloc +; +; unsigned __rt_alloc(unsigned minwords, void **block); +; +; This tries to allocate a block of sensible size >= minwords. Failing that, +; it allocates the largest possible block of sensible size. If it can't do +; that, it returns zero. *block is set to point to the start of the allocated +; block (NULL if none has been allocated). +; +; NOTE: works in units of WORDS, NOT bytes. +; +; In this implementation, sl - StackSlop marks the end of allocatable store. + + CMP a1, #MinHeapIncrement ; round up to at least + MOVLT a1, #MinHeapIncrement ; MinHeapIncrement words... + LDR a3, HeapLimitAdr + LDR a4, [a3] ; current heap high-water mark + SUB ip, sl, #StackSlop ; current stack low-water mark + CMP a4, ip + MOVGE a4, #0 ; no space, *block = NULL + STR a4, [a2] + MOVGE a1, #0 ; no space, return 0 + ADD a4, a4, a1, LSL #2 ; proposed new heap limit + CMP a4, ip + SUBGT a2, a4, ip ; byte overlap, >= 0 by earlier code + SUBGT a1, a1, a2, LSR #2 ; reduce word request + MOVGT a4, ip ; new high-water = stack low-water + STR a4, [a3] + RET +HeapLimitAdr + DCD HeapLimit + +;----------------------------------------------------------------------------; + AREA |C$$code$$__rt_stkovf|, CODE, READONLY +; The code area containing __rt_stkovf_* ; +;----------------------------------------------------------------------------; +; C stack-limit checking support. ; +; ; +; NOTES ; +; ; +; 1/ Stack-limit-checking is optional - you can compile your C code without ; +; stack-limit checks (#pragma nocheck_stack or cc -zps0). However, the ; +; cost of the check is (very) small and the value sometimes considerable. ; +; ; +; 2/ The limit check embeds knowledge of the memory layout and interacts ; +; with the primitive memory management supported by __rt_alloc. Here, we ; +; assume a single address space with the stack at the top growing down ; +; and the heap below it growing up, with a gap (free memory) in between. ; +; ; +; 3/ Failure of the stack-limit check is fatal. However, failure of the low- ; +; level heap allocator is passed back to its caller. ; +; ; +; 4/ This implementation never reduces the size of the stack. It simply ; +; moves the low-water mark monatonically downwards. It is easy to do ; +; better, but, of course, it takes more code and is more target-specific. ; +;----------------------------------------------------------------------------; + +|__rt_stkovf_split_small| ; stkovf_split_small_frame ; +; +; Enter here when a C function with frame size <= 256 bytes underflows +; the stack low-water mark + StackSlop (sl). The stack space required has +; already been claimed by decrementing sp, so we set the proposed sp (ip) +; to the actual sp and fall into the big-frame case. + + MOV ip, sp ; fall into big-frame case with size of 0. + +|__rt_stkovf_split_big| ; stkovf_split_big_frame ; +; +; Enter here when a C function with frame size > 256 bytes would underflow +; the stack low-water mark + StackSlop (sl). No stack space has been claimed +; but the proposed new stack pointer is in ip. + + SUB ip, sp, ip ; frame size required... + CMP ip, #DefaultStackIncrement ; rounded up to at least + MOVLT ip, #DefaultStackIncrement ; the default increment + + SUB sl, sl, ip + SUB sl, sl, #StackSlop ; new stack low-water mark + + LDR ip, HeapLimitAdr ; check doesn't collide with + LDR ip, [ip] ; the heap. + CMP ip, sl + ADD sl, sl, #StackSlop ; restore safety margin + BGT stackoverflow + RET ; and return if OK... + +stackoverflow + ADR ip, StackOverflowError + B save_regs_and_trap + +StackOverflowError + DCD 3 + DCB "stack overflow", 0 + ALIGN + + +;----------------------------------------------------------------------------; + AREA |C$$code$$__jmp|, CODE, READONLY +; The code area containing setjmp, longjmp ; +;----------------------------------------------------------------------------; +; Setjmp and longjmp support. ; +; ; +; NOTES ; +; ; +; 1/ Specific to C and not implementable in C. ; +; ; +; 2/ Interacts with stack management and possibly with memory management. ; +; e.g. on a chunked stack, longjmp must de-allocate jumped-over chunks. ; +; ; +; 3/ Must know whether the floating-point instruction-set is supported! ; +; (DEPENDS ON __rt_fpavailable to discover this). ; +; ; +;----------------------------------------------------------------------------; + + MAP 0 ; This structure maps the jmp_buf +sj_v1 # 4 ; data type assumed by the C compiler. +sj_v2 # 4 ; First, space to save the v-registers... +sj_v3 # 4 +sj_v4 # 4 +sj_v5 # 4 +sj_v6 # 4 +sj_sl # 4 ; then the frame registers sl, fp, sp (ap), +sj_fp # 4 ; and pc/lr... +sj_ap # 4 +sj_pc # 4 +sj_f4 # 3*4 ; and finally the floating-point reisters, +sj_f5 # 3*4 ; used only if floating point support is +sj_f6 # 3*4 ; available. +sj_f7 # 3*4 + + +|setjmp| ; setjmp +; +; int setjmp(jmp_buf env); +; Saves everything that might count as a register variable in 'env'. + + STMIA a1!, {v1-v6, sl, fp, sp, lr} + MOV v6, a1 ; v6 safe in env - use to point past + ; saved lr (at 1st FP slot) + BL |__rt_fpavailable| + CMP a1, #0 + BEQ setjmp_return ; no fp + STFE f4, [v6, #sj_f4-sj_f4] + STFE f5, [v6, #sj_f5-sj_f4] + STFE f6, [v6, #sj_f6-sj_f4] + STFE f7, [v6, #sj_f7-sj_f4] + MOV a1, #0 ; must return 0 from a direct call +setjmp_return + LDMDB v6, {v6, sl, fp, sp, lr} + RET + +|longjmp| ; longjmp ; +; int longjmp(jmp_buf env, int val); + + MOV v1, a1 ; save env ptr over call to fpavailable + MOVS v6, a2 ; ensure non-0 return value... + MOVEQ v6, #1 ; (must NOT return 0 on longjmp(env, 0)) + BL |__rt_fpavailable| + CMP a1, #0 + BEQ longjmp_return + LDFE f7, [v1, #sj_f7] + LDFE f6, [v1, #sj_f6] + LDFE f5, [v1, #sj_f5] + LDFE f4, [v1, #sj_f4] +longjmp_return + MOV a1, v6 + LDMIA v1, {v1-v6, sl, fp, sp, lr} + RET + +;----------------------------------------------------------------------------; + AREA |C$$code$$__divide|, CODE, READONLY +; The code area containing __rt_sdiv, __rt_udiv, __rt_sdiv_10, __rt_udiv10 ; +;----------------------------------------------------------------------------; +; GENERIC ARM FUNCTIONS - divide and remainder. ; +; ; +; NOTES ; +; ; +; 1/ You may wish to make these functions part of your O/S kernel, replacing ; +; the implementations here by branches to the relevant entry addresses. ; +; ; +; 2/ Each divide function is a div-rem function, returning the quotient in ; +; r0 and the remainder in r1. Thus (r0, r1) -> (r0/r1, r0%r1). This is ; +; understood by the C compiler. ; +; ; +; 3/ Because of its importance in many applications, divide by 10 is treated ; +; as a special case. The C compiler recognises divide by 10 and generates ; +; calls to __rt_{u,s}div10, as appropriate. ; +; ; +; 4/ Each of the implementations below has been coded with smallness as a ; +; higher priority than speed. Unrolling the loops will allow faster ; +; execution, but will produce much larger code. If the speed of divides ; +; is critical then unrolled versions can be extracted from the ARM ANSI C ; +; Library. ; +; ; +;----------------------------------------------------------------------------; + +; div_core is used by __rt_sdiv and __rt_udiv, and corrupts a3, a4 and ip +div_core + CMP a3, a4 + MOVHI a4, a4, ASL #1 + BHI div_core +div_core2 + CMP a2, a4 + ADC ip, ip, ip + SUBHS a2, a2, a4 + CMP a1, a4 + MOVLO a4, a4, LSR #1 + BLO div_core2 + MOV a1, ip + RET + +; Signed divide of a2 by a1: returns quotient in a1, remainder in a2 +; Quotient is truncated (rounded towards zero). +; Sign of remainder = sign of dividend. +; Destroys a3, a4 and ip +; Negates dividend and divisor, then does an unsigned divide; signs +; get sorted out again at the end. + +|__rt_sdiv| + MOVS a3, a1 + BEQ dividebyzero ; ip now unwanted + + RSBMI a1, a1, #0 ; absolute value of divisor + EOR a3, a3, a2 + ANDS ip, a2, #&80000000 + ORR a3, ip, a3, LSR #1 + STMFD sp!,{a3,lr} + ; saved a3: + ; bit 31 sign of dividend (= sign of remainder) + ; bit 30 sign of dividend EOR sign of divisor (= sign of quotient) + RSBNE a2, a2, #0 ; absolute value of dividend + + MOV a3, a2 + MOV a4, a1 + MOV ip, #0 + BL div_core + LDMFD sp!,{a3} + MOVS a3, a3, ASL #1 + RSBMI a1, a1, #0 + RSBCS a2, a2, #0 + IF {CONFIG} = 26 + LDMFD sp!,{pc}^ + ELSE + LDMFD sp!,{pc} + ENDIF + +; Unsigned divide of a2 by a1: returns quotient in a1, remainder in a2 +; Destroys a4, ip and r5 + +|__rt_udiv| + MOVS a4, a1 + BEQ dividebyzero + + MOV ip, #0 + MOV a3, #&80000000 + CMP a2, a3 + MOVLO a3, a2 + B div_core + +; +; Fast unsigned divide by 10: dividend in a1, divisor in a2. +; Returns quotient in a1, remainder in a2. +; Also destroys a3. +; +; Calculate x / 10 as (x * 2**32/10) / 2**32. +; That is, we calculate the most significant word of the double-length +; product. In fact, we calculate an approximation which may be 1 off +; because we've ignored a carry from the least significant word we didn't +; calculate. We correct for this by insisting that the remainder < 10 +; and by incrementing the quotient if it isn't. + +|__rt_udiv10| ; udiv10 ; + MOV a2, a1 + MOV a1, a1, LSR #1 + ADD a1, a1, a1, LSR #1 + ADD a1, a1, a1, LSR #4 + ADD a1, a1, a1, LSR #8 + ADD a1, a1, a1, LSR #16 + MOV a1, a1, LSR #3 + ADD a3, a1, a1, ASL #2 + SUB a2, a2, a3, ASL #1 + CMP a2, #10 + ADDGE a1, a1, #1 + SUBGE a2, a2, #10 + RET + +; +; Fast signed divide by 10: dividend in a1, divisor in a2. +; Returns quotient in a1, remainder in a2. +; Also destroys a3 and a4. +; Quotient is truncated (rounded towards zero). +; Make use of __rt_udiv10 + +|__rt_sdiv10| ; sdiv10 ; + MOV ip, lr + MOVS a4, a1 + RSBMI a1, a1, #0 + BL __rt_udiv10 + CMP a4, #0 + RSBMI a1, a1, #0 + RSBMI a2, a2, #0 + IF {CONFIG} = 26 + MOVS pc, ip + ELSE + MOV pc, ip + ENDIF + +; +; Test for division by zero (used when division is voided). + +|__rt_divtest| ; divtest ; + CMPS a1, #0 + RET NE +dividebyzero + ADR ip, DivideByZeroError + B save_regs_and_trap + +DivideByZeroError + DCD 1 + DCB "divide by 0", 0 + ALIGN + + END diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/RTSTAND1.H b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/RTSTAND1.H new file mode 100644 index 0000000..0366f05 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/RTSTAND1.H @@ -0,0 +1,56 @@ +/* + * Standalone C run-time kernel. + * Copyright (C) 1991 Advanced RISC Machines Limited. + */ + +#ifndef __rtstand_h +#define __rtstand_h + + +extern void __rt_exit(int /* code */); /* + * Terminate execution; equivalent to returning from main. + * NOTE: all other details are determined by your implementation. + */ + +typedef struct {unsigned errnum; char errmess[252];} __rt_error; +typedef struct {int r[16];} __rt_registers; + +extern void __err_handler(__rt_error *, __rt_registers *); + +extern int __rt_fpavailable(void); +/* + * Return non-0 iff there is support for the floating-point instruction set. + */ + +extern unsigned __rt_alloc(unsigned /*minwords*/, void ** /*block*/); +/* + * Tries to allocate a block of sensible size >= minwords. Failing that, + * it allocates the largest possible block (may have size zero). + * Sensible size is determined by your implementation (default: 256 words). + * *block is set to a pointer to the start of the allocated block + * (NULL if 'a block of size zero' has been allocated). + */ + +#ifdef __JMP_BUF_SIZE +typedef int jmp_buf[__JMP_BUF_SIZE]; +#else +typedef int jmp_buf[22]; /* size suitable for the ARM */ +#endif /* an array type suitable for holding the data */ + /* needed to restore a calling environment. */ +#ifdef __STDC__ +/* setjmp is a macro so that it cannot be used other than directly called. */ +/* NB that ANSI declare that anyone who undefined the setjmp macro or uses */ +/* (or defines) the name setjmp without including this header will get */ +/* what they deserve. NOTE: -pcc mode doesn't allow circular definitions...*/ +#define setjmp(jmp_buf) (setjmp(jmp_buf)) +#endif + +extern int setjmp(jmp_buf /*env*/); + +extern int longjmp(jmp_buf /*env*/, int /*val*/); + +typedef unsigned int size_t; /* others (e.g. ) define */ + +extern void *__rt_memmove(void * /*s1*/, const void * /*s2*/, size_t /*n*/); + +#endif diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/RTSTAND1.S b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/RTSTAND1.S new file mode 100644 index 0000000..7d85dfa --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/RTSTAND1.S @@ -0,0 +1,787 @@ +; Issue: 0.03/23-Feb-93 +; +; Purpose: Minimal, standalone, C-library kernel. +; +; Copyright (C) 1993 Advanced RISC Machines Limited. All rights reserved. +; +; Advanced RISC Machines Limited does not assume any liability arising out +; of this program or use thereof neither does it convey any licence under +; its intellectual property rights. +; +; Conditions of use: +; +; The terms and conditions under which this software is supplied to you and +; under which you may use it are described in your licence agreement with +; your supplier. +; +;----------------------------------------------------------------------------; +; ABOUT THIS CODE ; +; ; +; This code shows you how to write your own minimal, standalone, run-time ; +; support system for code compiled by Advanced RISC Machines's C Compiler. ; +; It can be assembled using Advanced RISC Machines's ARM assembler (armasm) ; +; or any assembler comaptible with it. ; +; ; +; This example code has been written to run under Advanced RISC Machines's ; +; ARM emulation system (ARMulator). It can also run without modification ; +; under Acorm Computer's "RISC OS" operating system for its ARM-based ; +; personal workstations. ; +; ; +; In fact, this code depends hardly at all on its target environment and is ; +; designed to be very easy to adapt to your particular ARM-based system. ; +; You can expect it to take about a couple of hours to re-target. ; +; ; +; Much of the code below is generic to the ARM processor and is completely ; +; independent of your ARM-based hardware or any operating system kernel that ; +; may run on it. To get going, you need write only 4 simple fns. ; +; ; +; WHAT THIS CODE PROVIDES: ; +; ; +; - Example, executable implementations (for the ARMulator) of the few ; +; simple functions you need to implement to customise this code to your ; +; environment. These include: ; +; - setting up the initial stack and heap and calling main (__main) ; +; - program termination (__rt_exit) ; +; - determining FP instruction-set availability (__rt_fpavailable) ; +; ; +; - Functions to help with heap allocation, stack-limit checking, setjmp ; +; and longjmp. These may need to be customised for your environment, ; +; but can almost certainly be used as-is in a first re-targetting. ; +; ; +; - Fully 'rolled' divide (and remainder) functions. ; +; ; +; WHAT THIS CODE DOES NOT PROVIDE ; +; ; +; - Support for handling traps, faults, escapes, exceptions or interrupts. ; +; ; +; - A way to print to the debugging channel (use in line SWIs) ; +; ; +;----------------------------------------------------------------------------; + +;----------------------------------------------------------------------------; +; The following constant is the Top Of Memory - Adjust this for your system ; +;----------------------------------------------------------------------------; + +TopOfMemory EQU 0x80000 ; 512Kb + +;----------------------------------------------------------------------------; +; Things you may wish to tune, but which you don't need to alter, follow. ; +;----------------------------------------------------------------------------; + +DefaultStackSize EQU 4*1024 ; The stack starts of this big unless + ; over-ridden by __root_stack_size. + +DefaultStackIncrement EQU 1*1024 ; At each overflow it grows by at + ; at least this many bytes. + +StackSlop EQU 512 ; sl is kept this far above the real + ; stack low-water mark. NOTE: MUST be + ; >= 256 or the compiled limit checks + ; will be invalidated. + +MinHeapIncrement EQU 256 ; Min number of WORDS to extend the + ; heap by on calling __rt_alloc. + + GBLL EnsureNoFPSupport +EnsureNoFPSupport SETL {FALSE} ; If {TRUE} then the availability of + ; Floating Point Support is ignored. + ; If {FALSE} then FP availability is + ; checked for. + ; Setting to {TRUE} saves a little + ; space. + +;----------------------------------------------------------------------------; +; Symbols defined in other, separately-assembled modules, must be IMPORTed. ; +; We import them WEAKly so that they need not be defined. ; +;----------------------------------------------------------------------------; + + IF EnsureNoFPSupport = {FALSE} + IMPORT |__fp_initialise|, WEAK + IMPORT |__fp_finalise|, WEAK + ENDIF + +;----------------------------------------------------------------------------; +; The existence of __fp_initialise (imported WEAKly) indicates that floating ; +; point support code (or the access stub thereof) has been linked with this ; +; application. If you wish to load the FP support code separately, you may ; +; want to define some other mechanism for detecting the presence/absence of ; +; floating point support. Note that setjmp and longjmp must know whether the ; +; floating-point instruction set is supported. ; +; __fp_initialise is called by __main and __fp_finalise is called by _exit. ; +;----------------------------------------------------------------------------; + + IMPORT |__root_stack_size|, WEAK + +;----------------------------------------------------------------------------; +; If __root_stack_size, also imported WEAKly, exists, the value it addresses ; +; is used as the initial size of the stack. It can be defined in your C ; +; program as, e.g. int __root_stack_size = 10000; /* 10KB initial stack */ ; +;----------------------------------------------------------------------------; + + IMPORT |__err_handler|, WEAK + +;----------------------------------------------------------------------------; +; If __err_handler exists, errors are passed to it; otherwise, we print a ; +; simple diagnostic message and exit. ; +;----------------------------------------------------------------------------; + + IMPORT |Image$$RW$$Limit| + +;----------------------------------------------------------------------------; +; Image$$RW$$Limit is a linker-created symbol marking the end of the image. ; +; Its value is used as the heap base. ; +;----------------------------------------------------------------------------; + + IMPORT main + +;----------------------------------------------------------------------------; +; The symbol main identifies the C function entered from this code. ; +;----------------------------------------------------------------------------; + +;----------------------------------------------------------------------------; +; THE MEMORY MODEL ASSUMED BY THIS IMPLEMENTATION ; +; ; +; +----------------+ <--- top of memory (high address) ; +; | Stack space | ; +; |................| <--- stack pointer (sp) ; +; | Free stack | ; +; |................| <--- stack limit pointer (sl) ; +; +----------------+ <--- stack low-water mark (sl - StackSlop) ; +; | | ; +; | Unused memory | ; +; | | ; +; +----------------+ <--- top of heap (HeapLimit) ; +; | | ; +; | Heap space | ; +; | | ; +; +----------------+ <--- top of application (Image$$RW$$Limit) ; +; | Static data | } ; +; |................| } the application's memory image ; +; | Code | } ; +; +----------------+ <--- application load address ; +;----------------------------------------------------------------------------; + +;----------------------------------------------------------------------------; +; Now the symbols we define and EXPORT from this this module. ; +;----------------------------------------------------------------------------; +; First, symbols identifying the four functions you have to implement to ; +; make this run-time kernel work on your hardware. ; +;----------------------------------------------------------------------------; + + EXPORT |__main| + EXPORT |__rt_exit| + EXPORT |__rt_fpavailable| + EXPORT |__rt_trap| + +;----------------------------------------------------------------------------; +; Then some simple support for C heap management. It interacts with stack- ; +; limit checking but should require no attention in a first re-targetting. ; +;----------------------------------------------------------------------------; + + EXPORT |__rt_alloc| + +;----------------------------------------------------------------------------; +; Next, optional support for C stack-limit checking. This code should need ; +; no attention in a first re-targetting. ; +;----------------------------------------------------------------------------; + + EXPORT |__rt_stkovf_split_small| ; veneer + EXPORT |__rt_stkovf_split_big| + +;----------------------------------------------------------------------------; +; Then two C-specific functions which should require no attention in a first ; +; re-targetting. Note that they depend on __rt_fpavailable. ; +;----------------------------------------------------------------------------; + + EXPORT |setjmp| + EXPORT |longjmp| + +;----------------------------------------------------------------------------; +; And, finally, generic ARM functions, referred to by the C compiler. ; +; You should not need to alter any of these unless you wish to incorporate ; +; them in your operating system kernel. See also later comments. ; +;----------------------------------------------------------------------------; + + EXPORT |__rt_udiv| + EXPORT |__rt_udiv10| + EXPORT |__rt_sdiv| + EXPORT |__rt_sdiv10| + EXPORT |__rt_divtest| + +;----------------------------------------------------------------------------; + AREA |C$$data| ; This module's data area ; +;----------------------------------------------------------------------------; + +HeapLimit + DCD |Image$$RW$$Limit| ; initialised by the linker. + +;----------------------------------------------------------------------------; +; This code has to run in but 26-bit ARM modes and 32-bit modes. To allow ; +; for this, the code is carefully written so that all PSR restoration in ; +; 26-bit mode is via the following macro. ; +;----------------------------------------------------------------------------; + + MACRO + RET $cond + IF {CONFIG} = 26 + MOV$cond.S pc, lr + ELSE + MOV$cond pc, lr + ENDIF + MEND + +;----------------------------------------------------------------------------; +; The following four SWI definitions are specific to ARMulator/RISC OS. ; +; However, you will need to replace the whole of this following section... ; +; and all uses of these SWIs should also be replaced. ; +;----------------------------------------------------------------------------; + +WriteC EQU 0 ; Write r0 to error/debug stream. +Write0 EQU 2 ; Write 0-terminated string pointed + ; to by r0 to error/debug stream. +Exit EQU 17 ; Terminate program execution. + +;----------------------------------------------------------------------------; + AREA |C$$code$$__main|, CODE, READONLY +; The code area containing __main, __rt_exit ; +;----------------------------------------------------------------------------; + + ENTRY ; Define the image entry point. + +|__main| +; +; This is the initial entry point to the image. +; Have to establish a stack for C +; No arguments are passed to main from an embedded application, +; so argc and argv are set up to 0 + + MOV sp, #TopOfMemory ; Initial stack pointer... + MOV fp, #0 ; No previous frame, so fp=0 + + LDR a3, RootStackSize + CMP a3, #0 ; Is RootStackSize defined? + LDRNE a3, [a3] ; Yes: use value... + CMPNE a3, #DefaultStackSize ; but check caller not being silly. + MOVLE a3, #DefaultStackSize ; No/silly: use default size. + + SUB sl, sp, a3 ; stack low-water mark + ADD sl, sl, #StackSlop ; sl = LWM + StackSlop + + IF EnsureNoFPSupport = {FALSE} + LDR a1, fp_initialise ; initialise FP code if present + CMP a1, #0 + MOVNE lr, pc + MOVNE pc, a1 + ENDIF + + MOV a1, #0 ; set argc to 0 + MOV a2, #0 ; and argv to NUL + BL main ; Call main, falling through to + ; exit on return. + +|__rt_exit| ; exit +; +; void __rt_exit(int code); +; Terminate execution, optionally setting return code (ignored here). +; MUST NOT RETURN. + + IF EnsureNoFPSupport = {FALSE} + LDR a2, fp_finalise ; finalise FP code if present + CMP a2, #0 + MOVNE lr, pc + MOVNE pc, a2 + ENDIF + SWI Exit ; suicide... + +RootStackSize + DCD |__root_stack_size| + + IF EnsureNoFPSupport = {FALSE} +fp_initialise + DCD |__fp_initialise| +fp_finalise + DCD |__fp_finalise| + ENDIF + +;----------------------------------------------------------------------------; + AREA |C$$code$$__rt_fpavailable|, CODE, READONLY +; The code area containing __rt_fpavailable ; +;----------------------------------------------------------------------------; + +|__rt_fpavailable| +; +; int __rt_fpavailable(); return non-0 if FP support code linked. + + IF EnsureNoFPSupport = {FALSE} + LDR a1, fp_initialise + ELSE + MOV a1, #0 + ENDIF + RET + +;----------------------------------------------------------------------------; + AREA |C$$code$$__rt_trap|, CODE, READONLY +; The code area containing __rt_trap ; +;----------------------------------------------------------------------------; +; Support for low-level failures - currently stack overflow, divide by 0 and ; +; floating-point exceptions. If there is a higher level handler, call it; ; +; otherwise, print a message and exit gracefully. ; +; ; +; NOTES ; +; ; +; typedef struct { unsigned code; char message[252];} __rt_error; ; +; typedef struct { unsigned r[16];} __rt_registers; ; +; ; +;----------------------------------------------------------------------------; + +|__rt_trap| +; +; void __rt_trap(__rt_error *e, __rt_registers *r); + + STMFD sp!, {a1} ; save e in case handler returns... + LDR ip, err_handler + CMP ip, #0 + MOVNE lr, pc + IF {CONFIG} = 26 + MOVNES pc, ip ; if got a handler, use it and + ELSE + MOVNE pc, ip ; if got a handler, use it and + ENDIF + LDMFD sp!, {v1} ; hope not to return... + + ADR a1, RTErrorHead + SWI Write0 ; write preamble... + ADD a1, v1, #4 + SWI Write0 ; write error diagnosis + ADR a1, RTErrorTail + SWI Write0 ; write postlude + MOV a1, #255 + B |__rt_exit| ; and terminate with non-zero exit code +err_handler + DCD |__err_handler| + +save_regs_and_trap + STMFD sp!, {sp, lr, pc} + STMFD sp!, {r0-r12} + STR lr, [sp, #4*15] ; caller's pc is my lr + MOV a2, sp + MOV a1, ip + B |__rt_trap| + +RTErrorHead + DCB 10, 13, "run time error: ", 0 + +RTErrorTail + DCB 10, 13, "program terminated", 10, 13, 10, 13, 0 + + ALIGN + +;----------------------------------------------------------------------------; +; YOU SHOULDN'T NEED TO ALTER ANY OF THE FOLLOWING IN A FIRST RETARGETTING. ; +;----------------------------------------------------------------------------; + +;----------------------------------------------------------------------------; + AREA |C$$code$$__rt_alloc|, CODE, READONLY +; The code area containing __rt_alloc ; +;----------------------------------------------------------------------------; +; Primitive support for heap memory management. ; +; ; +; NOTES ; +; ; +; 1/ The allocator embeds knowledge of the memory layout and interacts with ; +; the stack limit checking code. Here we assume a single address space ; +; with the stack at the top growing down and the heap below it growing ; +; up, with a gap (free memory) in between. ; +; ; +; 2/ Failure of the stack-limit check is fatal. However, failure of the low- ; +; level heap allocator is passed back to its caller. ; +;----------------------------------------------------------------------------; + + +|__rt_alloc| ; alloc +; +; unsigned __rt_alloc(unsigned minwords, void **block); +; +; This tries to allocate a block of sensible size >= minwords. Failing that, +; it allocates the largest possible block of sensible size. If it can't do +; that, it returns zero. *block is set to point to the start of the allocated +; block (NULL if none has been allocated). +; +; NOTE: works in units of WORDS, NOT bytes. +; +; In this implementation, sl - StackSlop marks the end of allocatable store. + + CMP a1, #MinHeapIncrement ; round up to at least + MOVLT a1, #MinHeapIncrement ; MinHeapIncrement words... + LDR a3, HeapLimitAdr + LDR a4, [a3] ; current heap high-water mark + SUB ip, sl, #StackSlop ; current stack low-water mark + CMP a4, ip + MOVGE a4, #0 ; no space, *block = NULL + STR a4, [a2] + MOVGE a1, #0 ; no space, return 0 + ADD a4, a4, a1, LSL #2 ; proposed new heap limit + CMP a4, ip + SUBGT a2, a4, ip ; byte overlap, >= 0 by earlier code + SUBGT a1, a1, a2, LSR #2 ; reduce word request + MOVGT a4, ip ; new high-water = stack low-water + STR a4, [a3] + RET +HeapLimitAdr + DCD HeapLimit + +;----------------------------------------------------------------------------; + AREA |C$$code$$__rt_stkovf|, CODE, READONLY +; The code area containing __rt_stkovf_* ; +;----------------------------------------------------------------------------; +; C stack-limit checking support. ; +; ; +; NOTES ; +; ; +; 1/ Stack-limit-checking is optional - you can compile your C code without ; +; stack-limit checks (#pragma nocheck_stack or cc -zps0). However, the ; +; cost of the check is (very) small and the value sometimes considerable. ; +; ; +; 2/ The limit check embeds knowledge of the memory layout and interacts ; +; with the primitive memory management supported by __rt_alloc. Here, we ; +; assume a single address space with the stack at the top growing down ; +; and the heap below it growing up, with a gap (free memory) in between. ; +; ; +; 3/ Failure of the stack-limit check is fatal. However, failure of the low- ; +; level heap allocator is passed back to its caller. ; +; ; +; 4/ This implementation never reduces the size of the stack. It simply ; +; moves the low-water mark monatonically downwards. It is easy to do ; +; better, but, of course, it takes more code and is more target-specific. ; +;----------------------------------------------------------------------------; + +|__rt_stkovf_split_small| ; stkovf_split_small_frame ; +; +; Enter here when a C function with frame size <= 256 bytes underflows +; the stack low-water mark + StackSlop (sl). The stack space required has +; already been claimed by decrementing sp, so we set the proposed sp (ip) +; to the actual sp and fall into the big-frame case. + + MOV ip, sp ; fall into big-frame case with size of 0. + +|__rt_stkovf_split_big| ; stkovf_split_big_frame ; +; +; Enter here when a C function with frame size > 256 bytes would underflow +; the stack low-water mark + StackSlop (sl). No stack space has been claimed +; but the proposed new stack pointer is in ip. + + SUB ip, sp, ip ; frame size required... + CMP ip, #DefaultStackIncrement ; rounded up to at least + MOVLT ip, #DefaultStackIncrement ; the default increment + + SUB sl, sl, ip + SUB sl, sl, #StackSlop ; new stack low-water mark + + LDR ip, HeapLimitAdr ; check doesn't collide with + LDR ip, [ip] ; the heap. + CMP ip, sl + ADD sl, sl, #StackSlop ; restore safety margin + BGT stackoverflow + RET ; and return if OK... + +stackoverflow + ADR ip, StackOverflowError + B save_regs_and_trap + +StackOverflowError + DCD 3 + DCB "stack overflow", 0 + ALIGN + + +;----------------------------------------------------------------------------; + AREA |C$$code$$__jmp|, CODE, READONLY +; The code area containing setjmp, longjmp ; +;----------------------------------------------------------------------------; +; Setjmp and longjmp support. ; +; ; +; NOTES ; +; ; +; 1/ Specific to C and not implementable in C. ; +; ; +; 2/ Interacts with stack management and possibly with memory management. ; +; e.g. on a chunked stack, longjmp must de-allocate jumped-over chunks. ; +; ; +; 3/ Must know whether the floating-point instruction-set is supported! ; +; (DEPENDS ON __rt_fpavailable to discover this). ; +; ; +;----------------------------------------------------------------------------; + + MAP 0 ; This structure maps the jmp_buf +sj_v1 # 4 ; data type assumed by the C compiler. +sj_v2 # 4 ; First, space to save the v-registers... +sj_v3 # 4 +sj_v4 # 4 +sj_v5 # 4 +sj_v6 # 4 +sj_sl # 4 ; then the frame registers sl, fp, sp (ap), +sj_fp # 4 ; and pc/lr... +sj_ap # 4 +sj_pc # 4 +sj_f4 # 3*4 ; and finally the floating-point reisters, +sj_f5 # 3*4 ; used only if floating point support is +sj_f6 # 3*4 ; available. +sj_f7 # 3*4 + + +|setjmp| ; setjmp +; +; int setjmp(jmp_buf env); +; Saves everything that might count as a register variable in 'env'. + + STMIA a1!, {v1-v6, sl, fp, sp, lr} + MOV v6, a1 ; v6 safe in env - use to point past + ; saved lr (at 1st FP slot) + BL |__rt_fpavailable| + CMP a1, #0 + BEQ setjmp_return ; no fp + STFE f4, [v6, #sj_f4-sj_f4] + STFE f5, [v6, #sj_f5-sj_f4] + STFE f6, [v6, #sj_f6-sj_f4] + STFE f7, [v6, #sj_f7-sj_f4] + MOV a1, #0 ; must return 0 from a direct call +setjmp_return + LDMDB v6, {v6, sl, fp, sp, lr} + RET + +|longjmp| ; longjmp ; +; int longjmp(jmp_buf env, int val); + + MOV v1, a1 ; save env ptr over call to fpavailable + MOVS v6, a2 ; ensure non-0 return value... + MOVEQ v6, #1 ; (must NOT return 0 on longjmp(env, 0)) + BL |__rt_fpavailable| + CMP a1, #0 + BEQ longjmp_return + LDFE f7, [v1, #sj_f7] + LDFE f6, [v1, #sj_f6] + LDFE f5, [v1, #sj_f5] + LDFE f4, [v1, #sj_f4] +longjmp_return + MOV a1, v6 + LDMIA v1, {v1-v6, sl, fp, sp, lr} + RET + +;----------------------------------------------------------------------------; + AREA |C$$code$$__divide|, CODE, READONLY +; The code area containing __rt_sdiv, __rt_udiv, __rt_sdiv_10, __rt_udiv10 ; +;----------------------------------------------------------------------------; +; GENERIC ARM FUNCTIONS - divide and remainder. ; +; ; +; NOTES ; +; ; +; 1/ You may wish to make these functions part of your O/S kernel, replacing ; +; the implementations here by branches to the relevant entry addresses. ; +; ; +; 2/ Each divide function is a div-rem function, returning the quotient in ; +; r0 and the remainder in r1. Thus (r0, r1) -> (r0/r1, r0%r1). This is ; +; understood by the C compiler. ; +; ; +; 3/ Because of its importance in many applications, divide by 10 is treated ; +; as a special case. The C compiler recognises divide by 10 and generates ; +; calls to __rt_{u,s}div10, as appropriate. ; +; ; +; 4/ Each of the implementations below has been coded with smallness as a ; +; higher priority than speed. Unrolling the loops will allow faster ; +; execution, but will produce much larger code. If the speed of divides ; +; is critical then unrolled versions can be extracted from the ARM ANSI C ; +; Library. ; +; ; +;----------------------------------------------------------------------------; + +; div_core is used by __rt_sdiv and __rt_udiv, and corrupts a3, a4 and ip +div_core + CMP a3, a4 + MOVHI a4, a4, ASL #1 + BHI div_core +div_core2 + CMP a2, a4 + ADC ip, ip, ip + SUBHS a2, a2, a4 + CMP a1, a4 + MOVLO a4, a4, LSR #1 + BLO div_core2 + MOV a1, ip + RET + +; Signed divide of a2 by a1: returns quotient in a1, remainder in a2 +; Quotient is truncated (rounded towards zero). +; Sign of remainder = sign of dividend. +; Destroys a3, a4 and ip +; Negates dividend and divisor, then does an unsigned divide; signs +; get sorted out again at the end. + +|__rt_sdiv| + MOVS a3, a1 + BEQ dividebyzero ; ip now unwanted + + RSBMI a1, a1, #0 ; absolute value of divisor + EOR a3, a3, a2 + ANDS ip, a2, #&80000000 + ORR a3, ip, a3, LSR #1 + STMFD sp!,{a3,lr} + ; saved a3: + ; bit 31 sign of dividend (= sign of remainder) + ; bit 30 sign of dividend EOR sign of divisor (= sign of quotient) + RSBNE a2, a2, #0 ; absolute value of dividend + + MOV a3, a2 + MOV a4, a1 + MOV ip, #0 + BL div_core + LDMFD sp!,{a3} + MOVS a3, a3, ASL #1 + RSBMI a1, a1, #0 + RSBCS a2, a2, #0 + IF {CONFIG} = 26 + LDMFD sp!,{pc}^ + ELSE + LDMFD sp!,{pc} + ENDIF + +; Unsigned divide of a2 by a1: returns quotient in a1, remainder in a2 +; Destroys a4, ip and r5 + +|__rt_udiv| + MOVS a4, a1 + BEQ dividebyzero + + MOV ip, #0 + MOV a3, #&80000000 + CMP a2, a3 + MOVLO a3, a2 + B div_core + +; +; Fast unsigned divide by 10: dividend in a1, divisor in a2. +; Returns quotient in a1, remainder in a2. +; Also destroys a3. +; +; Calculate x / 10 as (x * 2**32/10) / 2**32. +; That is, we calculate the most significant word of the double-length +; product. In fact, we calculate an approximation which may be 1 off +; because we've ignored a carry from the least significant word we didn't +; calculate. We correct for this by insisting that the remainder < 10 +; and by incrementing the quotient if it isn't. + +|__rt_udiv10| ; udiv10 ; + MOV a2, a1 + MOV a1, a1, LSR #1 + ADD a1, a1, a1, LSR #1 + ADD a1, a1, a1, LSR #4 + ADD a1, a1, a1, LSR #8 + ADD a1, a1, a1, LSR #16 + MOV a1, a1, LSR #3 + ADD a3, a1, a1, ASL #2 + SUB a2, a2, a3, ASL #1 + CMP a2, #10 + ADDGE a1, a1, #1 + SUBGE a2, a2, #10 + RET + +; +; Fast signed divide by 10: dividend in a1, divisor in a2. +; Returns quotient in a1, remainder in a2. +; Also destroys a3 and a4. +; Quotient is truncated (rounded towards zero). +; Make use of __rt_udiv10 + +|__rt_sdiv10| ; sdiv10 ; + MOV ip, lr + MOVS a4, a1 + RSBMI a1, a1, #0 + BL __rt_udiv10 + CMP a4, #0 + RSBMI a1, a1, #0 + RSBMI a2, a2, #0 + IF {CONFIG} = 26 + MOVS pc, ip + ELSE + MOV pc, ip + ENDIF + +; +; Test for division by zero (used when division is voided). + +|__rt_divtest| ; divtest ; + CMPS a1, #0 + RET NE +dividebyzero + ADR ip, DivideByZeroError + B save_regs_and_trap + +DivideByZeroError + DCD 1 + DCB "divide by 0", 0 + ALIGN + +;----------------------------------------------------------------------------; + AREA |C$$code$$__rt_memmove|, CODE, READONLY +; The code area containing __rt_memmove() extracted from the ARM C Library ; +; Note that as this was produced using armcc -apcs 3/32bit it is only ; +; intended for use in 32 bit modes ; +;----------------------------------------------------------------------------; + + EXPORT |__rt_memmove| +|__rt_memmove| + ORR a4,a1,a2 + ORR a4,a4,a3 + ANDS a4,a4,#3 + BNE |L000064.J4.__rt_memmove| + MOV a3,a3,LSR #2 + CMP a1,a2 + MOVLT a4,a1 + BLT |L000034.J9.__rt_memmove| + ADD a4,a1,a3,LSL #2 + ADD a2,a2,a3,LSL #2 + B |L000050.J13.__rt_memmove| +|L00002c.J8.__rt_memmove| + LDR ip,[a2],#4 + STR ip,[a4],#4 +|L000034.J9.__rt_memmove| + MOV ip,a3 + SUB a3,a3,#1 + CMP ip,#0 + BHI |L00002c.J8.__rt_memmove| + MOV pc,lr +|L000048.J12.__rt_memmove| + LDR ip,[a2,#-4]! + STR ip,[a4,#-4]! +|L000050.J13.__rt_memmove| + MOV ip,a3 + SUB a3,a3,#1 + CMP ip,#0 + BHI |L000048.J12.__rt_memmove| + MOV pc,lr +|L000064.J4.__rt_memmove| + CMP a1,a2 + MOVLT a4,a1 + BLT |L000084.J19.__rt_memmove| + ADD a4,a1,a3 + ADD a2,a2,a3 + B |L0000a0.J23.__rt_memmove| +|L00007c.J18.__rt_memmove| + LDRB ip,[a2],#1 + STRB ip,[a4],#1 +|L000084.J19.__rt_memmove| + MOV ip,a3 + SUB a3,a3,#1 + CMP ip,#0 + BHI |L00007c.J18.__rt_memmove| + MOV pc,lr +|L000098.J22.__rt_memmove| + LDRB ip,[a2,#-1]! + STRB ip,[a4,#-1]! +|L0000a0.J23.__rt_memmove| + MOV ip,a3 + SUB a3,a3,#1 + CMP ip,#0 + BHI |L000098.J22.__rt_memmove| + MOV pc,lr + + END diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/THUMB/RTSTAND.S b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/THUMB/RTSTAND.S new file mode 100644 index 0000000..605926f --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/CLSTAND/THUMB/RTSTAND.S @@ -0,0 +1,819 @@ +; Issue: 1.00/19-Jan-95 +; +; Purpose: Minimal, standalone, C-library kernel for Thumb +; +; Copyright (C) 1995 Advanced RISC Machines Limited. All rights reserved. +; +; Advanced RISC Machines Limited does not assume any liability arising out +; of this program or use thereof neither does it convey any licence under +; its intellectual property rights. +; +; Conditions of use: +; +; The terms and conditions under which this software is supplied to you and +; under which you may use it are described in your licence agreement with +; your supplier. +; +;----------------------------------------------------------------------------; +; ABOUT THIS CODE ; +; ; +; This code shows you how to write your own minimal, standalone, Thumb ; +; run-time support system for code compiled by Advanced RISC Machines's ; +; Thumb C Compiler. It can be assembled using Advanced RISC Machines's Thumb ; +; assembler. ; +; ; +; This code may be used to build a ROM image. It may also be run under ; +; Advanced RISC Machines's ARM emulation system (ARMulator). ; +; ; +; In fact, this code depends hardly at all on its target environment and is ; +; designed to be very easy to adapt to your particular ARM-based system. ; +; ; +; Much of the code below is generic to the ARM processor and is completely ; +; independent of your ARM-based hardware or any operating system kernel that ; +; may run on it. To get going, you need write only 4 simple fns. ; +; ; +; WHAT THIS CODE PROVIDES: ; +; ; +; - Example, executable implementations of the few ; +; simple functions you need to implement to customise this code to your ; +; environment. These include: ; +; - setting up the initial stack and heap and calling main (__main) ; +; - program termination (__rt_exit) ; +; ; +; - Functions to help with heap allocation, stack-limit checking, setjmp ; +; and longjmp. These may need to be customised for your environment, ; +; but can almost certainly be used as-is in a first re-targetting. ; +; ; +; - Fully 'rolled' divide (and remainder) functions. ; +; ; +; WHAT THIS CODE DOES NOT PROVIDE ; +; ; +; - Support for handling traps, faults, escapes, exceptions or interrupts. ; +; ; +; - A way to print to the debugging channel (use in line SWIs) ; +; ; +;----------------------------------------------------------------------------; + +;----------------------------------------------------------------------------; +; The following constant is the Top Of RAM - Adjust this for your system ; +;----------------------------------------------------------------------------; + +TopOfMemory EQU 0x80000 ; 512Kb + +;----------------------------------------------------------------------------; +; Things you may wish to tune, but which you don't need to alter, follow. ; +;----------------------------------------------------------------------------; + +DefaultStackSize EQU 4*1024 ; The stack starts of this big unless + ; over-ridden by __root_stack_size. + +DefaultStackIncrement EQU 1*1024 ; At each overflow it grows by at + ; at least this many bytes. + +StackSlop EQU 512 ; sl is kept this far above the real + ; stack low-water mark. NOTE: MUST be + ; >= 256 or the compiled limit checks + ; will be invalidated. + +MinHeapIncrement EQU 256 ; Min number of WORDS to extend the + ; heap by on calling __rt_alloc. + +;----------------------------------------------------------------------------; +; Symbols defined in other, separately-assembled modules, must be IMPORTed. ; +; We import them WEAKly so that they need not be defined. ; +;----------------------------------------------------------------------------; + + IMPORT __root_stack_size, WEAK + +;----------------------------------------------------------------------------; +; If __root_stack_size, also imported WEAKly, exists, the value it addresses ; +; is used as the initial size of the stack. It can be defined in your C ; +; program as, e.g. int __root_stack_size = 10000; /* 10KB initial stack */ ; +;----------------------------------------------------------------------------; + + IMPORT __err_handler, WEAK + +;----------------------------------------------------------------------------; +; If __err_handler exists, errors are passed to it; otherwise, we print a ; +; simple diagnostic message and exit. ; +;----------------------------------------------------------------------------; + + IMPORT |Image$$RO$$Base| + IMPORT |Image$$RO$$Limit| + IMPORT |Image$$RW$$Base| + IMPORT |Image$$RW$$Limit| + IMPORT |Image$$ZI$$Base| + IMPORT |Image$$ZI$$Limit| + +;----------------------------------------------------------------------------; +; The above symbols are created by the linker to define various sections in ; +; the ROM/RAM image. ; +; ; +; Image$$RO$$Base defines the code (ROM) base address ; +; Image$$RO$$Limit defines the code limit and the start of a section of ; +; data initialisation values which are copied to RAM ; +; in __main below before main is called. ; +; Image$$RW$$Base defines the data (RAM) base address ; +; Image$$RW$$Limit defines the data end address ; +; Image$$ZI$$Base defines the base of a section to be initialised with 0s ; +; Image$$ZI$$Limit defines the end of the region to be initialised with 0s ; +; (must be the same as Image$$RW$$Limit in this model) ; +;----------------------------------------------------------------------------; + + IMPORT main + +;----------------------------------------------------------------------------; +; The symbol main identifies the C function entered from this code. ; +;----------------------------------------------------------------------------; + +;----------------------------------------------------------------------------; +; THE MEMORY MODEL ASSUMED BY THIS IMPLEMENTATION ; +; ; +; RAM ; +; ; +; +------------------+ <--- top of memory (high address) ; +; | Stack space | ; +; |..................| <--- stack pointer (sp) ; +; | Free stack | ; +; |..................| <--- stack limit pointer (sl) ; +; +------------------+ <--- stack low-water mark (sl - StackSlop) ; +; | | ; +; | Unused memory | ; +; | | ; +; +------------------+ <--- top of heap (HeapLimit) ; +; | | ; +; | Heap space | ; +; | | ; +; +------------------+ <--- top of fixed data (Image$$RW$$Limit) ; +; | Zero init data | (=Image$$ZI$$Limit) ; +; +------------------+ <--- top of initialised (Image$$ZI$$Base) ; +; | Initialised data | data ; +; +------------------+ <--- Data base address (Image$$RW$$Base) ; +; ; +; ROM ; +; ; +; +------------------+ <--- Top of ROM image ; +; | Initial values | } Copied to "Initialised data" section in RAM ; +; | for Init data | } on statup in __main below ; +; +------------------+ <--- End of code (Image$$RO$$Limit) ; +; | Code | ; +; +------------------+ <--- Code base address (Image$$RO$$Base) ; +;----------------------------------------------------------------------------; + +;----------------------------------------------------------------------------; +; Now the symbols we define and EXPORT from this module. ; +;----------------------------------------------------------------------------; +; First, symbols identifying the four functions you have to implement to ; +; make this run-time kernel work on your hardware. ; +;----------------------------------------------------------------------------; + + EXPORT __main + EXPORT __rt_exit + EXPORT __rt_trap + +;----------------------------------------------------------------------------; +; Then some simple support for C heap management. It interacts with stack- ; +; limit checking but should require no attention in a first re-targetting. ; +;----------------------------------------------------------------------------; + + EXPORT __rt_alloc + +;----------------------------------------------------------------------------; +; Next, optional support for C stack-limit checking. This code should need ; +; no attention in a first re-targetting. ; +;----------------------------------------------------------------------------; + + EXPORT __16__rt_stkovf_split_small ; veneer + EXPORT __16__rt_stkovf_split_big + +;----------------------------------------------------------------------------; +; Then two C-specific functions which should require no attention in a first ; +; re-targetting. ; +;----------------------------------------------------------------------------; + + EXPORT setjmp + EXPORT longjmp + +;----------------------------------------------------------------------------; +; And, finally, generic ARM functions, referred to by the C compiler. ; +; You should not need to alter any of these unless you wish to incorporate ; +; them in your operating system kernel. See also later comments. ; +;----------------------------------------------------------------------------; + + EXPORT __16__rt_udiv + EXPORT __16__rt_udiv10 + EXPORT __16__rt_sdiv + EXPORT __16__rt_sdiv10 + EXPORT __16__rt_divtest + +;----------------------------------------------------------------------------; + AREA |C$$data| ; This module's data area ; +;----------------------------------------------------------------------------; + +HeapLimit + DCD |Image$$RW$$Limit| ; initialised by the linker. + +;----------------------------------------------------------------------------; +; Macro to return from a function ; +; We use the BX instruction below rather than MOV pc, lr so that the return ; +; will work correctly if we are called from ARM state ; +;----------------------------------------------------------------------------; + + MACRO + RET + BX lr + MEND + +;----------------------------------------------------------------------------; +; The following four SWI definitions are specific to ARMulator/RISC OS. ; +; However, you will need to replace the whole of this following section... ; +; and all uses of these SWIs should also be replaced. ; +;----------------------------------------------------------------------------; + +WriteC EQU 0 ; Write r0 to error/debug stream. +Write0 EQU 2 ; Write 0-terminated string pointed + ; to by r0 to error/debug stream. +Exit EQU 17 ; Terminate program execution. + + CODE16 + +TBit EQU 1 ; Bit to set in register to enter + ; Thumb state with BX + +;----------------------------------------------------------------------------; +; Use area name "!!!" so this area is placed first as AREAs are sorted by +; area name. + AREA |!!!|, CODE, READONLY, INTERWORK +; The code area containing __main, __rt_exit ; +;----------------------------------------------------------------------------; + + ENTRY ; Define the image entry point. + +__main + CODE32 ; Entered in ARM state presumeably + ADR lr, __main_16+TBit + BX lr + CODE16 +__main_16 +; +; This is the initial entry point to the image. +; Have to establish a stack for C +; No arguments are passed to main from an embedded application, +; so argc and argv are set up to 0 + + LDR r0, =TopOfMemory ; Set up initial stack pointer + MOV sp, r0 + + MOV r0, #0 + MOV fp, r0 ; No previous frame, so fp=0 + + LDR r0, =DefaultStackSize + LDR r1, =__root_stack_size + CMP r1, #0 ; Is RootStackSize defined? + BEQ %F0 ; No => Use default + LDR r1, [r1] ; Yes => Get value + CMP r1, r0 ; But check value >= DefaultStackSize + BCC %F0 ; if >= use default in r0. + MOV r0, r1 +0 + MOV r1, sp + SUB r1, r0 ; stack low limit + LDR r0, =StackSlop + ADD r1, r0 ; plus a bit spare + MOV sl, r1 + +; Now initialise the data segment by copying the initial values from ROM +; to RAM and by clearing the zero init segment to 0. + + LDR r0, =|Image$$RO$$Limit| ; Get pointer to ROM initial values + LDR r1, =|Image$$RW$$Base| ; And RAM data segment + LDR r3, =|Image$$ZI$$Base| ; Zero init base = top of initialised segment + CMP r0, r1 ; Check that they are different, (they may be + BEQ %F3 ; the same if the image is running in RAM) + B %F2 +1 + LDMIA r0!, {r2} ; Copy the initialising data over + STMIA r1!, {r2} +2 CMP r1, r3 + BCC %B1 +3 + LDR r1, =|Image$$ZI$$Limit| ; Top of area to be zero initialised + MOV r2, #0 + B %F5 + +4 STMIA r3!, {r2} ; Clear out zero init segment +5 CMP r3, r1 + BCC %B4 + + MOV r0, #0 ; set argc to 0 + MOV r1, #0 ; and argv to NUL + BL main ; Call main, falling through to + ; exit on return. + +__rt_exit ; exit +; +; void __rt_exit(int code); +; Terminate execution, optionally setting return code (ignored here). +; MUST NOT RETURN. + + SWI Exit ; suicide... + +;----------------------------------------------------------------------------; + AREA |C$$code$$__rt_trap|, CODE, READONLY +; The code area containing __rt_trap ; +;----------------------------------------------------------------------------; +; Support for low-level failures - currently stack overflow and divide by 0. ; +; If there is a higher level handler, call it otherwise, print a message and ; +; exit gracefully. ; +; ; +; NOTES ; +; ; +; typedef struct { unsigned code; char message[252];} __rt_error; ; +; typedef struct { unsigned r[16];} __rt_registers; ; +; ; +;----------------------------------------------------------------------------; + +__rt_trap +; +; void __rt_trap(__rt_error *e, __rt_registers *r); + + PUSH {r0} ; save e in case handler returns... + LDR r3, =__err_handler + CMP r3, #0 + BEQ %F0 + + BL call_via_r3 ; Call the routine pointed to by R3 + ; Note: BL sets bit 0 of LR so return will + ; be to Thumb state. This is why we use this + ; rather than the sequence + ; MOV lr, pc + ; BX r3 + ; which may return to ARM state! + +0 + ADR r0, RTErrorHead ; No handler, or handler returned + SWI Write0 ; write preamble... + POP {r0} + ADD r0, #4 + SWI Write0 ; write error diagnosis + ADR r0, RTErrorTail + SWI Write0 ; write postlude + MOV a1, #255 + BL __rt_exit ; and terminate with non-zero exit code + +call_via_r3 + BX r3 + +; SP has already been decremented by 16 * 4 and R0..R7 saved. +; IP points to the error description +; R7 contains the LR register which has been destroyed as a BL was required +; to get here. +save_regs_and_trap + MOV ip, r0 + MOV r0, r8 + MOV r1, r9 + MOV r2, r10 + MOV r3, r11 + MOV r4, r12 + ADD r5, sp, #16*4 ; Take account of previous SP adjustment + ADD r6, sp, #8*4 ; Pointer to hi reg save area + STMIA r6!, {r0-r5, r7} + STR r7, [sp, #15*4] ; Save my pc as callers lr + MOV a2, sp + MOV a1, ip + B __rt_trap + + ALIGN +RTErrorHead + DCB 10, 13, "run time error: ", 0 + + ALIGN +RTErrorTail + DCB 10, 13, "program terminated", 10, 13, 10, 13, 0 + + ALIGN + +;----------------------------------------------------------------------------; +; YOU SHOULDN'T NEED TO ALTER ANY OF THE FOLLOWING IN A FIRST RETARGETTING. ; +;----------------------------------------------------------------------------; + +;----------------------------------------------------------------------------; + AREA |C$$code$$__rt_alloc|, CODE, READONLY +; The code area containing __rt_alloc ; +;----------------------------------------------------------------------------; +; Primitive support for heap memory management. ; +; ; +; NOTES ; +; ; +; 1/ The allocator embeds knowledge of the memory layout and interacts with ; +; the stack limit checking code. Here we assume a single address space ; +; with the stack at the top growing down and the heap below it growing ; +; up, with a gap (free memory) in between. ; +; ; +; 2/ Failure of the stack-limit check is fatal. However, failure of the low- ; +; level heap allocator is passed back to its caller. ; +;----------------------------------------------------------------------------; + + +__rt_alloc ; alloc +; +; unsigned __rt_alloc(unsigned minwords, void **block); +; +; This tries to allocate a block of sensible size >= minwords. Failing that, +; it allocates the largest possible block of sensible size. If it can't do +; that, it returns zero. *block is set to point to the start of the allocated +; block (NULL if none has been allocated). +; +; NOTE: works in units of WORDS, NOT bytes. +; +; In this implementation, sl - StackSlop marks the end of allocatable store. + + LDR r2, =MinHeapIncrement + CMP r0, r2 ; round up to at least + BGE %F0 + MOV r0, r2 ; MinHeapIncrement words... +0 + MOV ip, sl + LDR r2, =-StackSlop + ADD ip, r2 ; current stack low-water mark + LDR r2, =HeapLimit + LDR r3, [r2] ; current heap high-water mark + CMP r3, ip + BLE %F1 + MOV r3, #0 ; no space, *block = NULL + MOV r0, #0 ; no space, return 0 +1 + STR r3, [r1] + LSL r0, #2 ; Convert size request to bytes + ADD r3, r0 ; proposed new heap limit + CMP r3, ip + BLE %F2 + ADD r0, ip ; Reduce size request by amount + SUB r0, r3 ; of overlap + MOV r3, ip ; new high-water = stack low-water +2 + STR r3, [r2] + LSR r0, #2 ; Convert return size to words + RET + +;----------------------------------------------------------------------------; + AREA |C$$code$$__rt_stkovf|, CODE, READONLY +; The code area containing __rt_stkovf_* ; + + [ :LNOT::DEF:STACK_EXTENSION + GBLL STACK_EXTENSION +STACK_EXTENSION SETL {FALSE} + ] +;----------------------------------------------------------------------------; +; C stack-limit checking support. ; +; ; +; NOTES ; +; ; +; 1/ This code is only called if stack checking is enabled with the ; +; -apcs 3/swst option on the Thumb compiler. Typically you will only do ; +; this when debugging. ; +; ; +; 2/ The code may be configured to either perform automatic stack extension ; +; or to generate an error on stack overflow. By default it is set up to ; +; generate an error. To change this to extend the stack uncomment the ; +; following line. ; +; ; +;STACK_EXTENSION SETL {TRUE} ; +; ; +; 3/ The stack extension embeds knowledge of the memory layout and interacts ; +; with the primitive memory management supported by __rt_alloc. Here, we ; +; assume a single address space with the stack at the top growing down ; +; and the heap below it growing up, with a gap (free memory) in between. ; +; ; +; 4/ Failure of the stack-limit check is fatal. However, failure of the low- ; +; level heap allocator is passed back to its caller. ; +; ; +; 5/ This implementation of stack extension never reduces the size of the ; +; stack. It simply moves the low-water mark downwards. It is easy to do ; +; better, but, of course, it takes more code and is more target-specific. ; +;----------------------------------------------------------------------------; + +__16__rt_stkovf_split_small +; +; Enter here when a C function with frame size <= 256 bytes underflows +; the stack low-water mark + StackSlop (sl). The stack space required has +; already been claimed by decrementing sp, so we set the proposed sp (ip) +; to the actual sp and fall into the big-frame case. + + [ STACK_EXTENSION + MOV ip, sp ; fall into big-frame case with size of 0. + ] + +__16__rt_stkovf_split_big +; +; Enter here when a C function with frame size > 256 bytes would underflow +; the stack low-water mark + StackSlop (sl). No stack space has been claimed +; but the proposed new stack pointer is in ip. + + [ STACK_EXTENSION + PUSH {r0,r1} + ADD r0, sp, #8 ; get original sp + MOV r1, ip + SUB r0, r1 ; frame size required... + LDR r1, =DefaultStackIncrement + CMP r0, r1 ; rounded up to at least + BGE %F0 + MOV r0, r1 ; the default increment +0 + MOV r1, sl + SUB r1, r0 + LDR r0, =StackSlop + SUB r1, r0 ; new stack low-water mark + MOV sl, r1 + + LDR r1, =HeapLimit + LDR r1, [r1] ; check doesn't collide with + CMP r1, sl ; the heap. + ADD sl, r0 ; restore safety margin + ; (preserves CC) + + POP {r0, r1} + BGT stackoverflow + RET ; and return if OK... + + ] +stackoverflow + SUB sp, sp, #8*4 ; Room for R8..R15 + PUSH {r0-r7} + MOV r7, lr + ADR r0, StackOverflowError + BL save_regs_and_trap + + ALIGN +StackOverflowError + DCD 3 + DCB "stack overflow", 0 + ALIGN + + +;----------------------------------------------------------------------------; + AREA |C$$code$$__jmp|, CODE, READONLY +; The code area containing setjmp, longjmp ; +;----------------------------------------------------------------------------; +; Setjmp and longjmp support. ; +; ; +; NOTES ; +; ; +; 1/ Specific to C and not implementable in C. ; +; ; +; 2/ Interacts with stack management and possibly with memory management. ; +; e.g. on a chunked stack, longjmp must de-allocate jumped-over chunks. ; +; ; +;----------------------------------------------------------------------------; + + MAP 0 ; This structure maps the jmp_buf +sj_v1 # 4 ; data type assumed by the C compiler. +sj_v2 # 4 ; First, space to save the v-registers... +sj_v3 # 4 +sj_v4 # 4 +sj_v5 # 4 +sj_v6 # 4 +sj_sl # 4 ; then the frame registers sl, fp, sp (ap), +sj_fp # 4 ; and pc/lr... +sj_ap # 4 +sj_pc # 4 + + +setjmp +; +; int setjmp(jmp_buf env); +; Saves everything that might count as a register variable in 'env'. + + STMIA a1!, {r4-r7} + MOV r0, r8 + MOV r1, r9 + MOV r2, sl + MOV r3, fp + STMIA a1!, {r0-r3} + MOV r0, sp + MOV r1, lr + STMIA a1!, {r0-r1} + MOV a1, #0 ; must return 0 from a direct call + RET + +longjmp +; int longjmp(jmp_buf env, int val); + + ADD r0, #4*4 + LDMIA r0!, {r2-r7} ; Restore r8 .. lr + MOV r8, r2 + MOV r9, r3 + MOV sl, r4 + MOV fp, r5 + MOV sp, r6 + MOV lr, r7 + SUB r0, #10*4 + LDMIA r0!, {r4-r7} ; Restore v1..v4 + MOV r0, r1 + BNE %F0 + MOV r0, #1 ; Must not return 0 +0 + RET + +;----------------------------------------------------------------------------; + AREA |C$$code$$__divide|, CODE, READONLY +; The code area containing __rt_sdiv, __rt_udiv, __rt_sdiv_10, __rt_udiv10 ; +;----------------------------------------------------------------------------; +; GENERIC ARM FUNCTIONS - divide and remainder. ; +; ; +; NOTES ; +; ; +; 1/ You may wish to make these functions part of your O/S kernel, replacing ; +; the implementations here by branches to the relevant entry addresses. ; +; ; +; 2/ Each divide function is a div-rem function, returning the quotient in ; +; r0 and the remainder in r1. Thus (r0, r1) -> (r0/r1, r0%r1). This is ; +; understood by the C compiler. ; +; ; +; 3/ Because of its importance in many applications, divide by 10 is treated ; +; as a special case. The C compiler recognises divide by 10 and generates ; +; calls to __rt_{u,s}div10, as appropriate. ; +; ; +; 4/ Each of the implementations below has been coded with smallness as a ; +; higher priority than speed. Unrolling the loops will allow faster ; +; execution, but will produce much larger code. If the speed of divides ; +; is critical then unrolled versions can be extracted from the ARM ANSI C ; +; Library. ; +; ; +;----------------------------------------------------------------------------; + +; Signed divide of a2 by a1: returns quotient in a1, remainder in a2 +; Quotient is truncated (rounded towards zero). +; Sign of remainder = sign of dividend. +; Destroys a3, a4 and ip +; Negates dividend and divisor, then does an unsigned divide; signs +; get sorted out again at the end. + +__16__rt_sdiv + ASR a4, a2, #31 + EOR a2, a4 + SUB a2, a4 + + ASR a3, a1, #31 + EOR a1, a3 + SUB a1, a3 + + BEQ dividebyzero + + PUSH {a3, a4} ; Save so we can look at signs later on + + LSR a4, a2, #1 + MOV a3, a1 + +s_loop CMP a3, a4 + BNLS %FT0 + LSL a3, #1 +0 BLO s_loop + + MOV a4, #0 + B %FT0 +s_loop2 LSR a3, #1 +0 CMP a2, a3 + ADC a4, a4 + CMP a2, a3 + BCC %FT0 + SUB a2, a3 +0 + CMP a3, a1 + BNE s_loop2 + MOV a1, a4 + + POP {a3, a4} + + EOR a3, a4 + EOR a1, a3 + SUB a1, a3 + + EOR a2, a4 + SUB a2, a4 + + RET + +; Unsigned divide of a2 by a1: returns quotient in a1, remainder in a2 +; Destroys a4, ip and r5 + +__16__rt_udiv + LSR a4, a2, #1 + MOV a3, a1 + BEQ dividebyzero + +u_loop CMP a3, a4 + BNLS %FT0 + LSL a3, #1 +0 BLO u_loop + + MOV a4, #0 + B %FT0 +u_loop2 LSR a3, #1 +0 CMP a2, a3 + ADC a4, a4 + CMP a2, a3 + BCC %FT0 + SUB a2, a3 +0 + CMP a3, a1 + BNE u_loop2 + MOV a1, a4 + + RET + +; +; Fast unsigned divide by 10: dividend in a1, divisor in a2. +; Returns quotient in a1, remainder in a2. +; Also destroys a3. +; +; Calculate x / 10 as (x * 2**32/10) / 2**32. +; That is, we calculate the most significant word of the double-length +; product. In fact, we calculate an approximation which may be 1 off +; because we've ignored a carry from the least significant word we didn't +; calculate. We correct for this by insisting that the remainder < 10 +; and by incrementing the quotient if it isn't. + +__16__rt_udiv10 ; udiv10 ; + MOV a2, a1 + LSR a1, #1 + LSR a3, a1, #1 + ADD a1, a3 + LSR a3, a1, #4 + ADD a1, a3 + LSR a3, a1, #8 + ADD a1, a3 + LSR a3, a1, #16 + ADD a1, a3 + LSR a1, #3 + ASL a3, a1, #2 + ADD a3, a1 + ASL a3, #1 + SUB a2, a3 + CMP a2, #10 + BLT %FT0 + ADD a1, #1 + SUB a2, #10 +0 + RET + +; +; Fast signed divide by 10: dividend in a1, divisor in a2. +; Returns quotient in a1, remainder in a2. +; Also destroys a3 and a4. +; Quotient is truncated (rounded towards zero). +; Make use of __rt_udiv10 + +__16__rt_sdiv10 + ASR a4, a1, #31 + EOR a1, a4 + SUB a1, a4 + + MOV a2, a1 + LSR a1, #1 + LSR a3, a1, #1 + ADD a1, a3 + LSR a3, a1, #4 + ADD a1, a3 + LSR a3, a1, #8 + ADD a1, a3 + LSR a3, a1, #16 + ADD a1, a3 + LSR a1, #3 + ASL a3, a1, #2 + ADD a3, a1 + ASL a3, #1 + SUB a2, a3 + CMP a2, #10 + BLT %FT0 + ADD a1, #1 + SUB a2, #10 +0 + EOR a1, a4 + SUB a1, a4 + EOR a2, a4 + SUB a2, a4 + RET + +; +; Test for division by zero (used when division is voided). + +__16__rt_divtest ; divtest ; + CMPS a1, #0 + BEQ dividebyzero + RET + +dividebyzero + SUB sp, sp, #8*4 ; Room for R8..R15 + PUSH {r0-r7} + MOV r7, lr + ADR r0, DivideByZeroError + BL save_regs_and_trap + + ALIGN +DivideByZeroError + DCD 1 + DCB "divide by 0", 0 + ALIGN + + END diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/DHRY/ARMSD.MAP b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/DHRY/ARMSD.MAP new file mode 100644 index 0000000..c8941ad --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/DHRY/ARMSD.MAP @@ -0,0 +1 @@ +00000000 80000000 RAM 4 RW 135/85 135/85 diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/DHRY/DHRY.APJ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/DHRY/DHRY.APJ new file mode 100644 index 0000000..442bb95 Binary files /dev/null and b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/DHRY/DHRY.APJ differ diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/DHRY/DHRY.H b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/DHRY/DHRY.H new file mode 100644 index 0000000..9d5c9e7 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/DHRY/DHRY.H @@ -0,0 +1,431 @@ +/* + **************************************************************************** + * + * "DHRYSTONE" Benchmark Program + * ----------------------------- + * + * Version: C, Version 2.1 + * + * File: dhry.h (part 1 of 3) + * + * Date: May 25, 1988 + * + * Author: Reinhold P. Weicker + * Siemens AG, E STE 35 + * Postfach 3240 + * 8520 Erlangen + * Germany (West) + * Phone: [xxx-49]-9131-7-20330 + * (8-17 Central European Time) + * Usenet: ..!mcvax!unido!estevax!weicker + * + * Original Version (in Ada) published in + * "Communications of the ACM" vol. 27., no. 10 (Oct. 1984), + * pp. 1013 - 1030, together with the statistics + * on which the distribution of statements etc. is based. + * + * In this C version, the following C library functions are used: + * - strcpy, strcmp (inside the measurement loop) + * - printf, scanf (outside the measurement loop) + * In addition, Berkeley UNIX system calls "times ()" or "time ()" + * are used for execution time measurement. For measurements + * on other systems, these calls have to be changed. + * + * Collection of Results: + * Reinhold Weicker (address see above) and + * + * Rick Richardson + * PC Research. Inc. + * 94 Apple Orchard Drive + * Tinton Falls, NJ 07724 + * Phone: (201) 389-8963 (9-17 EST) + * Usenet: ...!uunet!pcrat!rick + * + * Please send results to Rick Richardson and/or Reinhold Weicker. + * Complete information should be given on hardware and software used. + * Hardware information includes: Machine type, CPU, type and size + * of caches; for microprocessors: clock frequency, memory speed + * (number of wait states). + * Software information includes: Compiler (and runtime library) + * manufacturer and version, compilation switches, OS version. + * The Operating System version may give an indication about the + * compiler; Dhrystone itself performs no OS calls in the measurement loop. + * + * The complete output generated by the program should be mailed + * such that at least some checks for correctness can be made. + * + *************************************************************************** + * + * History: This version C/2.1 has been made for two reasons: + * + * 1) There is an obvious need for a common C version of + * Dhrystone, since C is at present the most popular system + * programming language for the class of processors + * (microcomputers, minicomputers) where Dhrystone is used most. + * There should be, as far as possible, only one C version of + * Dhrystone such that results can be compared without + * restrictions. In the past, the C versions distributed + * by Rick Richardson (Version 1.1) and by Reinhold Weicker + * had small (though not significant) differences. + * + * 2) As far as it is possible without changes to the Dhrystone + * statistics, optimizing compilers should be prevented from + * removing significant statements. + * + * This C version has been developed in cooperation with + * Rick Richardson (Tinton Falls, NJ), it incorporates many + * ideas from the "Version 1.1" distributed previously by + * him over the UNIX network Usenet. + * I also thank Chaim Benedelac (National Semiconductor), + * David Ditzel (SUN), Earl Killian and John Mashey (MIPS), + * Alan Smith and Rafael Saavedra-Barrera (UC at Berkeley) + * for their help with comments on earlier versions of the + * benchmark. + * + * Changes: In the initialization part, this version follows mostly + * Rick Richardson's version distributed via Usenet, not the + * version distributed earlier via floppy disk by Reinhold Weicker. + * As a concession to older compilers, names have been made + * unique within the first 8 characters. + * Inside the measurement loop, this version follows the + * version previously distributed by Reinhold Weicker. + * + * At several places in the benchmark, code has been added, + * but within the measurement loop only in branches that + * are not executed. The intention is that optimizing compilers + * should be prevented from moving code out of the measurement + * loop, or from removing code altogether. Since the statements + * that are executed within the measurement loop have NOT been + * changed, the numbers defining the "Dhrystone distribution" + * (distribution of statements, operand types and locality) + * still hold. Except for sophisticated optimizing compilers, + * execution times for this version should be the same as + * for previous versions. + * + * Since it has proven difficult to subtract the time for the + * measurement loop overhead in a correct way, the loop check + * has been made a part of the benchmark. This does have + * an impact - though a very minor one - on the distribution + * statistics which have been updated for this version. + * + * All changes within the measurement loop are described + * and discussed in the companion paper "Rationale for + * Dhrystone version 2". + * + * Because of the self-imposed limitation that the order and + * distribution of the executed statements should not be + * changed, there are still cases where optimizing compilers + * may not generate code for some statements. To a certain + * degree, this is unavoidable for small synthetic benchmarks. + * Users of the benchmark are advised to check code listings + * whether code is generated for all statements of Dhrystone. + * + * Version 2.1 is identical to version 2.0 distributed via + * the UNIX network Usenet in March 1988 except that it corrects + * some minor deficiencies that were found by users of version 2.0. + * The only change within the measurement loop is that a + * non-executed "else" part was added to the "if" statement in + * Func_3, and a non-executed "else" part removed from Proc_3. + * + *************************************************************************** + * + * Defines: The following "Defines" are possible: + * -DREG=register (default: Not defined) + * As an approximation to what an average C programmer + * might do, the "register" storage class is applied + * (if enabled by -DREG=register) + * - for local variables, if they are used (dynamically) + * five or more times + * - for parameters if they are used (dynamically) + * six or more times + * Note that an optimal "register" strategy is + * compiler-dependent, and that "register" declarations + * do not necessarily lead to faster execution. + * -DNOSTRUCTASSIGN (default: Not defined) + * Define if the C compiler does not support + * assignment of structures. + * -DNOENUMS (default: Not defined) + * Define if the C compiler does not support + * enumeration types. + * -DTIMES (default) + * -DTIME + * The "times" function of UNIX (returning process times) + * or the "time" function (returning wallclock time) + * is used for measurement. + * For single user machines, "time ()" is adequate. For + * multi-user machines where you cannot get single-user + * access, use the "times ()" function. If you have + * neither, use a stopwatch in the dead of night. + * "printf"s are provided marking the points "Start Timer" + * and "Stop Timer". DO NOT use the UNIX "time(1)" + * command, as this will measure the total time to + * run this program, which will (erroneously) include + * the time to allocate storage (malloc) and to perform + * the initialization. + * -DHZ=nnn + * In Berkeley UNIX, the function "times" returns process + * time in 1/HZ seconds, with HZ = 60 for most systems. + * CHECK YOUR SYSTEM DESCRIPTION BEFORE YOU JUST APPLY + * A VALUE. + * + *************************************************************************** + * + * Compilation model and measurement (IMPORTANT): + * + * This C version of Dhrystone consists of three files: + * - dhry.h (this file, containing global definitions and comments) + * - dhry_1.c (containing the code corresponding to Ada package Pack_1) + * - dhry_2.c (containing the code corresponding to Ada package Pack_2) + * + * The following "ground rules" apply for measurements: + * - Separate compilation + * - No procedure merging + * - Otherwise, compiler optimizations are allowed but should be indicated + * - Default results are those without register declarations + * See the companion paper "Rationale for Dhrystone Version 2" for a more + * detailed discussion of these ground rules. + * + * For 16-Bit processors (e.g. 80186, 80286), times for all compilation + * models ("small", "medium", "large" etc.) should be given if possible, + * together with a definition of these models for the compiler system used. + * + ************************************************************************** + * + * Dhrystone (C version) statistics: + * + * [Comment from the first distribution, updated for version 2. + * Note that because of language differences, the numbers are slightly + * different from the Ada version.] + * + * The following program contains statements of a high level programming + * language (here: C) in a distribution considered representative: + * + * assignments 52 (51.0 %) + * control statements 33 (32.4 %) + * procedure, function calls 17 (16.7 %) + * + * 103 statements are dynamically executed. The program is balanced with + * respect to the three aspects: + * + * - statement type + * - operand type + * - operand locality + * operand global, local, parameter, or constant. + * + * The combination of these three aspects is balanced only approximately. + * + * 1. Statement Type: + * ----------------- number + * + * V1 = V2 9 + * (incl. V1 = F(..) + * V = Constant 12 + * Assignment, 7 + * with array element + * Assignment, 6 + * with record component + * -- + * 34 34 + * + * X = Y +|-|"&&"|"|" Z 5 + * X = Y +|-|"==" Constant 6 + * X = X +|- 1 3 + * X = Y *|/ Z 2 + * X = Expression, 1 + * two operators + * X = Expression, 1 + * three operators + * -- + * 18 18 + * + * if .... 14 + * with "else" 7 + * without "else" 7 + * executed 3 + * not executed 4 + * for ... 7 | counted every time + * while ... 4 | the loop condition + * do ... while 1 | is evaluated + * switch ... 1 + * break 1 + * declaration with 1 + * initialization + * -- + * 34 34 + * + * P (...) procedure call 11 + * user procedure 10 + * library procedure 1 + * X = F (...) + * function call 6 + * user function 5 + * library function 1 + * -- + * 17 17 + * --- + * 103 + * + * The average number of parameters in procedure or function calls + * is 1.82 (not counting the function values aX * + * + * 2. Operators + * ------------ + * number approximate + * percentage + * + * Arithmetic 32 50.8 + * + * + 21 33.3 + * - 7 11.1 + * * 3 4.8 + * / (int div) 1 1.6 + * + * Comparison 27 42.8 + * + * == 9 14.3 + * /= 4 6.3 + * > 1 1.6 + * < 3 4.8 + * >= 1 1.6 + * <= 9 14.3 + * + * Logic 4 6.3 + * + * && (AND-THEN) 1 1.6 + * | (OR) 1 1.6 + * ! (NOT) 2 3.2 + * + * -- ----- + * 63 100.1 + * + * + * 3. Operand Type (counted once per operand reference): + * --------------- + * number approximate + * percentage + * + * Integer 175 72.3 % + * Character 45 18.6 % + * Pointer 12 5.0 % + * String30 6 2.5 % + * Array 2 0.8 % + * Record 2 0.8 % + * --- ------- + * 242 100.0 % + * + * When there is an access path leading to the final operand (e.g. a record + * component), only the final data type on the access path is counted. + * + * + * 4. Operand Locality: + * ------------------- + * number approximate + * percentage + * + * local variable 114 47.1 % + * global variable 22 9.1 % + * parameter 45 18.6 % + * value 23 9.5 % + * reference 22 9.1 % + * function result 6 2.5 % + * constant 55 22.7 % + * --- ------- + * 242 100.0 % + * + * + * The program does not compute anything meaningful, but it is syntactically + * and semantically correct. All variables have a value assigned to them + * before they are used as a source operand. + * + * There has been no explicit effort to account for the effects of a + * cache, or to balance the use of long or short displacements for code or + * data. + * + *************************************************************************** + */ + +/* Compiler and system dependent definitions: */ + +#ifndef TIME +#undef TIMES +#define TIMES +#endif + /* Use times(2) time function unless */ + /* explicitly defined otherwise */ + +#ifdef MSC_CLOCK +#undef HZ +#undef TIMES +#include +#define HZ CLK_TCK +#endif + /* Use Microsoft C hi-res clock */ + +#ifdef TIMES +#include +#include + /* for "times" */ +#endif + +#define Mic_secs_Per_Second 1000000.0 + /* Berkeley UNIX C returns process times in seconds/HZ */ + +#ifdef NOSTRUCTASSIGN +#define structassign(d, s) memcpy(&(d), &(s), sizeof(d)) +#else +#define structassign(d, s) d = s +#endif + +#ifdef NOENUM +#define Ident_1 0 +#define Ident_2 1 +#define Ident_3 2 +#define Ident_4 3 +#define Ident_5 4 + typedef int Enumeration; +#else + typedef enum {Ident_1, Ident_2, Ident_3, Ident_4, Ident_5} + Enumeration; +#endif + /* for boolean and enumeration types in Ada, Pascal */ + +/* General definitions: */ + +#include + /* for strcpy, strcmp */ + +#define Null 0 + /* Value of a Null pointer */ +#define true 1 +#define false 0 + +typedef int One_Thirty; +typedef int One_Fifty; +typedef char Capital_Letter; +typedef int Boolean; +typedef char Str_30 [31]; +typedef int Arr_1_Dim [50]; +typedef int Arr_2_Dim [50] [50]; + +typedef struct record + { + struct record *Ptr_Comp; + Enumeration Discr; + union { + struct { + Enumeration Enum_Comp; + int Int_Comp; + char Str_Comp [31]; + } var_1; + struct { + Enumeration E_Comp_2; + char Str_2_Comp [31]; + } var_2; + struct { + char Ch_1_Comp; + char Ch_2_Comp; + } var_3; + } variant; + } Rec_Type, *Rec_Pointer; + + diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/DHRY/DHRY_1.C b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/DHRY/DHRY_1.C new file mode 100644 index 0000000..f5ba7a7 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/DHRY/DHRY_1.C @@ -0,0 +1,395 @@ +/* + **************************************************************************** + * + * "DHRYSTONE" Benchmark Program + * ----------------------------- + * + * Version: C, Version 2.1 + * + * File: dhry_1.c (part 2 of 3) + * + * Date: May 25, 1988 + * + * Author: Reinhold P. Weicker + * + **************************************************************************** + */ + +#include "dhry.h" + +/* Global Variables: */ + +Rec_Pointer Ptr_Glob, + Next_Ptr_Glob; +int Int_Glob; +Boolean Bool_Glob; +char Ch_1_Glob, + Ch_2_Glob; +int Arr_1_Glob [50]; +int Arr_2_Glob [50] [50]; + +extern char *malloc (); +Enumeration Func_1 (); + /* forward declaration necessary since Enumeration may not simply be int */ + +#ifndef REG + Boolean Reg = false; +#define REG + /* REG becomes defined as empty */ + /* i.e. no register variables */ +#else + Boolean Reg = true; +#endif + +/* variables for time measurement: */ + +#ifdef TIMES +struct tms time_info; +extern int times (); + /* see library function "times" */ +#define Too_Small_Time (2*HZ) + /* Measurements should last at least about 2 seconds */ +#endif +#ifdef TIME +extern long time(); + /* see library function "time" */ +#define Too_Small_Time 2 + /* Measurements should last at least 2 seconds */ +#endif +#ifdef MSC_CLOCK +extern clock_t clock(); +#define Too_Small_Time (2*HZ) +#endif + +long Begin_Time, + End_Time, + User_Time; +float Microseconds, + Dhrystones_Per_Second; + +/* end of variables for time measurement */ + + +main () +/*****/ + + /* main program, corresponds to procedures */ + /* Main and Proc_0 in the Ada version */ +{ + One_Fifty Int_1_Loc; + REG One_Fifty Int_2_Loc; + One_Fifty Int_3_Loc; + REG char Ch_Index; + Enumeration Enum_Loc; + Str_30 Str_1_Loc; + Str_30 Str_2_Loc; + REG int Run_Index; + REG int Number_Of_Runs; + + /* Initializations */ + + Next_Ptr_Glob = (Rec_Pointer) malloc (sizeof (Rec_Type)); + Ptr_Glob = (Rec_Pointer) malloc (sizeof (Rec_Type)); + + Ptr_Glob->Ptr_Comp = Next_Ptr_Glob; + Ptr_Glob->Discr = Ident_1; + Ptr_Glob->variant.var_1.Enum_Comp = Ident_3; + Ptr_Glob->variant.var_1.Int_Comp = 40; + strcpy (Ptr_Glob->variant.var_1.Str_Comp, + "DHRYSTONE PROGRAM, SOME STRING"); + strcpy (Str_1_Loc, "DHRYSTONE PROGRAM, 1'ST STRING"); + + Arr_2_Glob [8][7] = 10; + /* Was missing in published program. Without this statement, */ + /* Arr_2_Glob [8][7] would have an undefined value. */ + /* Warning: With 16-Bit processors and Number_Of_Runs > 32000, */ + /* overflow may occur for this array element. */ + + printf ("\n"); + printf ("Dhrystone Benchmark, Version 2.1 (Language: C)\n"); + printf ("\n"); + if (Reg) + { + printf ("Program compiled with 'register' attribute\n"); + printf ("\n"); + } + else + { + printf ("Program compiled without 'register' attribute\n"); + printf ("\n"); + } + printf ("Please give the number of runs through the benchmark: "); + { + int n; + scanf ("%d", &n); + Number_Of_Runs = n; + } + printf ("\n"); + + printf ("Execution starts, %d runs through Dhrystone\n", Number_Of_Runs); + + /***************/ + /* Start timer */ + /***************/ + +#ifdef TIMES + times (&time_info); + Begin_Time = (long) time_info.tms_utime; +#endif +#ifdef TIME + Begin_Time = time ( (long *) 0); +#endif +#ifdef MSC_CLOCK + Begin_Time = clock(); +#endif + + for (Run_Index = 1; Run_Index <= Number_Of_Runs; ++Run_Index) + { + + Proc_5(); + Proc_4(); + /* Ch_1_Glob == 'A', Ch_2_Glob == 'B', Bool_Glob == true */ + Int_1_Loc = 2; + Int_2_Loc = 3; + strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 2'ND STRING"); + Enum_Loc = Ident_2; + Bool_Glob = ! Func_2 (Str_1_Loc, Str_2_Loc); + /* Bool_Glob == 1 */ + while (Int_1_Loc < Int_2_Loc) /* loop body executed once */ + { + Int_3_Loc = 5 * Int_1_Loc - Int_2_Loc; + /* Int_3_Loc == 7 */ + Proc_7 (Int_1_Loc, Int_2_Loc, &Int_3_Loc); + /* Int_3_Loc == 7 */ + Int_1_Loc += 1; + } /* while */ + /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */ + Proc_8 (Arr_1_Glob, Arr_2_Glob, Int_1_Loc, Int_3_Loc); + /* Int_Glob == 5 */ + Proc_1 (Ptr_Glob); + for (Ch_Index = 'A'; Ch_Index <= Ch_2_Glob; ++Ch_Index) + /* loop body executed twice */ + { + if (Enum_Loc == Func_1 (Ch_Index, 'C')) + /* then, not executed */ + { + Proc_6 (Ident_1, &Enum_Loc); + strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 3'RD STRING"); + Int_2_Loc = Run_Index; + Int_Glob = Run_Index; + } + } + /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */ + Int_2_Loc = Int_2_Loc * Int_1_Loc; + Int_1_Loc = Int_2_Loc / Int_3_Loc; + Int_2_Loc = 7 * (Int_2_Loc - Int_3_Loc) - Int_1_Loc; + /* Int_1_Loc == 1, Int_2_Loc == 13, Int_3_Loc == 7 */ + Proc_2 (&Int_1_Loc); + /* Int_1_Loc == 5 */ + + } /* loop "for Run_Index" */ + + /**************/ + /* Stop timer */ + /**************/ + +#ifdef TIMES + times (&time_info); + End_Time = (long) time_info.tms_utime; +#endif +#ifdef TIME + End_Time = time ( (long *) 0); +#endif +#ifdef MSC_CLOCK + End_Time = clock(); +#endif + + printf ("Execution ends\n"); + printf ("\n"); + printf ("Final values of the variables used in the benchmark:\n"); + printf ("\n"); + printf ("Int_Glob: %d\n", Int_Glob); + printf (" should be: %d\n", 5); + printf ("Bool_Glob: %d\n", Bool_Glob); + printf (" should be: %d\n", 1); + printf ("Ch_1_Glob: %c\n", Ch_1_Glob); + printf (" should be: %c\n", 'A'); + printf ("Ch_2_Glob: %c\n", Ch_2_Glob); + printf (" should be: %c\n", 'B'); + printf ("Arr_1_Glob[8]: %d\n", Arr_1_Glob[8]); + printf (" should be: %d\n", 7); + printf ("Arr_2_Glob[8][7]: %d\n", Arr_2_Glob[8][7]); + printf (" should be: Number_Of_Runs + 10\n"); + printf ("Ptr_Glob->\n"); + printf (" Ptr_Comp: %d\n", (int) Ptr_Glob->Ptr_Comp); + printf (" should be: (implementation-dependent)\n"); + printf (" Discr: %d\n", Ptr_Glob->Discr); + printf (" should be: %d\n", 0); + printf (" Enum_Comp: %d\n", Ptr_Glob->variant.var_1.Enum_Comp); + printf (" should be: %d\n", 2); + printf (" Int_Comp: %d\n", Ptr_Glob->variant.var_1.Int_Comp); + printf (" should be: %d\n", 17); + printf (" Str_Comp: %s\n", Ptr_Glob->variant.var_1.Str_Comp); + printf (" should be: DHRYSTONE PROGRAM, SOME STRING\n"); + printf ("Next_Ptr_Glob->\n"); + printf (" Ptr_Comp: %d\n", (int) Next_Ptr_Glob->Ptr_Comp); + printf (" should be: (implementation-dependent), same as above\n"); + printf (" Discr: %d\n", Next_Ptr_Glob->Discr); + printf (" should be: %d\n", 0); + printf (" Enum_Comp: %d\n", Next_Ptr_Glob->variant.var_1.Enum_Comp); + printf (" should be: %d\n", 1); + printf (" Int_Comp: %d\n", Next_Ptr_Glob->variant.var_1.Int_Comp); + printf (" should be: %d\n", 18); + printf (" Str_Comp: %s\n", + Next_Ptr_Glob->variant.var_1.Str_Comp); + printf (" should be: DHRYSTONE PROGRAM, SOME STRING\n"); + printf ("Int_1_Loc: %d\n", Int_1_Loc); + printf (" should be: %d\n", 5); + printf ("Int_2_Loc: %d\n", Int_2_Loc); + printf (" should be: %d\n", 13); + printf ("Int_3_Loc: %d\n", Int_3_Loc); + printf (" should be: %d\n", 7); + printf ("Enum_Loc: %d\n", Enum_Loc); + printf (" should be: %d\n", 1); + printf ("Str_1_Loc: %s\n", Str_1_Loc); + printf (" should be: DHRYSTONE PROGRAM, 1'ST STRING\n"); + printf ("Str_2_Loc: %s\n", Str_2_Loc); + printf (" should be: DHRYSTONE PROGRAM, 2'ND STRING\n"); + printf ("\n"); + + User_Time = End_Time - Begin_Time; + + if (User_Time < Too_Small_Time) + { + printf ("Measured time too small to obtain meaningful results\n"); + printf ("Please increase number of runs\n"); + printf ("\n"); + } + else + { +#ifdef TIME + Microseconds = (float) User_Time * Mic_secs_Per_Second + / (float) Number_Of_Runs; + Dhrystones_Per_Second = (float) Number_Of_Runs / (float) User_Time; +#else + Microseconds = (float) User_Time * Mic_secs_Per_Second + / ((float) HZ * ((float) Number_Of_Runs)); + Dhrystones_Per_Second = ((float) HZ * (float) Number_Of_Runs) + / (float) User_Time; +#endif + printf ("Microseconds for one run through Dhrystone: "); + printf ("%6.1f \n", Microseconds); + printf ("Dhrystones per Second: "); + printf ("%6.1f \n", Dhrystones_Per_Second); + printf ("\n"); + } + +} + + +Proc_1 (Ptr_Val_Par) +/******************/ + +REG Rec_Pointer Ptr_Val_Par; + /* executed once */ +{ + REG Rec_Pointer Next_Record = Ptr_Val_Par->Ptr_Comp; + /* == Ptr_Glob_Next */ + /* Local variable, initialized with Ptr_Val_Par->Ptr_Comp, */ + /* corresponds to "rename" in Ada, "with" in Pascal */ + + structassign (*Ptr_Val_Par->Ptr_Comp, *Ptr_Glob); + Ptr_Val_Par->variant.var_1.Int_Comp = 5; + Next_Record->variant.var_1.Int_Comp + = Ptr_Val_Par->variant.var_1.Int_Comp; + Next_Record->Ptr_Comp = Ptr_Val_Par->Ptr_Comp; + Proc_3 (&Next_Record->Ptr_Comp); + /* Ptr_Val_Par->Ptr_Comp->Ptr_Comp + == Ptr_Glob->Ptr_Comp */ + if (Next_Record->Discr == Ident_1) + /* then, executed */ + { + Next_Record->variant.var_1.Int_Comp = 6; + Proc_6 (Ptr_Val_Par->variant.var_1.Enum_Comp, + &Next_Record->variant.var_1.Enum_Comp); + Next_Record->Ptr_Comp = Ptr_Glob->Ptr_Comp; + Proc_7 (Next_Record->variant.var_1.Int_Comp, 10, + &Next_Record->variant.var_1.Int_Comp); + } + else /* not executed */ + structassign (*Ptr_Val_Par, *Ptr_Val_Par->Ptr_Comp); +} /* Proc_1 */ + + +Proc_2 (Int_Par_Ref) +/******************/ + /* executed once */ + /* *Int_Par_Ref == 1, becomes 4 */ + +One_Fifty *Int_Par_Ref; +{ + One_Fifty Int_Loc; + Enumeration Enum_Loc; + + Int_Loc = *Int_Par_Ref + 10; + do /* executed once */ + if (Ch_1_Glob == 'A') + /* then, executed */ + { + Int_Loc -= 1; + *Int_Par_Ref = Int_Loc - Int_Glob; + Enum_Loc = Ident_1; + } /* if */ + while (Enum_Loc != Ident_1); /* true */ +} /* Proc_2 */ + + +Proc_3 (Ptr_Ref_Par) +/******************/ + /* executed once */ + /* Ptr_Ref_Par becomes Ptr_Glob */ + +Rec_Pointer *Ptr_Ref_Par; + +{ + if (Ptr_Glob != Null) + /* then, executed */ + *Ptr_Ref_Par = Ptr_Glob->Ptr_Comp; + Proc_7 (10, Int_Glob, &Ptr_Glob->variant.var_1.Int_Comp); +} /* Proc_3 */ + + +Proc_4 () /* without parameters */ +/*******/ + /* executed once */ +{ + Boolean Bool_Loc; + + Bool_Loc = Ch_1_Glob == 'A'; + Bool_Glob = Bool_Loc | Bool_Glob; + Ch_2_Glob = 'B'; +} /* Proc_4 */ + + +Proc_5 () /* without parameters */ +/*******/ + /* executed once */ +{ + Ch_1_Glob = 'A'; + Bool_Glob = false; +} /* Proc_5 */ + + + /* Procedure for the assignment of structures, */ + /* if the C compiler doesn't support this feature */ +#ifdef NOSTRUCTASSIGN +memcpy (d, s, l) +register char *d; +register char *s; +register int l; +{ + while (l--) *d++ = *s++; +} +#endif + + diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/DHRY/DHRY_2.C b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/DHRY/DHRY_2.C new file mode 100644 index 0000000..ed0e5b7 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/DHRY/DHRY_2.C @@ -0,0 +1,192 @@ +/* + **************************************************************************** + * + * "DHRYSTONE" Benchmark Program + * ----------------------------- + * + * Version: C, Version 2.1 + * + * File: dhry_2.c (part 3 of 3) + * + * Date: May 25, 1988 + * + * Author: Reinhold P. Weicker + * + **************************************************************************** + */ + +#include "dhry.h" + +#ifndef REG +#define REG + /* REG becomes defined as empty */ + /* i.e. no register variables */ +#endif + +extern int Int_Glob; +extern char Ch_1_Glob; + + +Proc_6 (Enum_Val_Par, Enum_Ref_Par) +/*********************************/ + /* executed once */ + /* Enum_Val_Par == Ident_3, Enum_Ref_Par becomes Ident_2 */ + +Enumeration Enum_Val_Par; +Enumeration *Enum_Ref_Par; +{ + *Enum_Ref_Par = Enum_Val_Par; + if (! Func_3 (Enum_Val_Par)) + /* then, not executed */ + *Enum_Ref_Par = Ident_4; + switch (Enum_Val_Par) + { + case Ident_1: + *Enum_Ref_Par = Ident_1; + break; + case Ident_2: + if (Int_Glob > 100) + /* then */ + *Enum_Ref_Par = Ident_1; + else *Enum_Ref_Par = Ident_4; + break; + case Ident_3: /* executed */ + *Enum_Ref_Par = Ident_2; + break; + case Ident_4: break; + case Ident_5: + *Enum_Ref_Par = Ident_3; + break; + } /* switch */ +} /* Proc_6 */ + + +Proc_7 (Int_1_Par_Val, Int_2_Par_Val, Int_Par_Ref) +/**********************************************/ + /* executed three times */ + /* first call: Int_1_Par_Val == 2, Int_2_Par_Val == 3, */ + /* Int_Par_Ref becomes 7 */ + /* second call: Int_1_Par_Val == 10, Int_2_Par_Val == 5, */ + /* Int_Par_Ref becomes 17 */ + /* third call: Int_1_Par_Val == 6, Int_2_Par_Val == 10, */ + /* Int_Par_Ref becomes 18 */ +One_Fifty Int_1_Par_Val; +One_Fifty Int_2_Par_Val; +One_Fifty *Int_Par_Ref; +{ + One_Fifty Int_Loc; + + Int_Loc = Int_1_Par_Val + 2; + *Int_Par_Ref = Int_2_Par_Val + Int_Loc; +} /* Proc_7 */ + + +Proc_8 (Arr_1_Par_Ref, Arr_2_Par_Ref, Int_1_Par_Val, Int_2_Par_Val) +/*********************************************************************/ + /* executed once */ + /* Int_Par_Val_1 == 3 */ + /* Int_Par_Val_2 == 7 */ +Arr_1_Dim Arr_1_Par_Ref; +Arr_2_Dim Arr_2_Par_Ref; +int Int_1_Par_Val; +int Int_2_Par_Val; +{ + REG One_Fifty Int_Index; + REG One_Fifty Int_Loc; + + Int_Loc = Int_1_Par_Val + 5; + Arr_1_Par_Ref [Int_Loc] = Int_2_Par_Val; + Arr_1_Par_Ref [Int_Loc+1] = Arr_1_Par_Ref [Int_Loc]; + Arr_1_Par_Ref [Int_Loc+30] = Int_Loc; + for (Int_Index = Int_Loc; Int_Index <= Int_Loc+1; ++Int_Index) + Arr_2_Par_Ref [Int_Loc] [Int_Index] = Int_Loc; + Arr_2_Par_Ref [Int_Loc] [Int_Loc-1] += 1; + Arr_2_Par_Ref [Int_Loc+20] [Int_Loc] = Arr_1_Par_Ref [Int_Loc]; + Int_Glob = 5; +} /* Proc_8 */ + + +Enumeration Func_1 (Ch_1_Par_Val, Ch_2_Par_Val) +/*************************************************/ + /* executed three times */ + /* first call: Ch_1_Par_Val == 'H', Ch_2_Par_Val == 'R' */ + /* second call: Ch_1_Par_Val == 'A', Ch_2_Par_Val == 'C' */ + /* third call: Ch_1_Par_Val == 'B', Ch_2_Par_Val == 'C' */ + +Capital_Letter Ch_1_Par_Val; +Capital_Letter Ch_2_Par_Val; +{ + Capital_Letter Ch_1_Loc; + Capital_Letter Ch_2_Loc; + + Ch_1_Loc = Ch_1_Par_Val; + Ch_2_Loc = Ch_1_Loc; + if (Ch_2_Loc != Ch_2_Par_Val) + /* then, executed */ + return (Ident_1); + else /* not executed */ + { + Ch_1_Glob = Ch_1_Loc; + return (Ident_2); + } +} /* Func_1 */ + + +Boolean Func_2 (Str_1_Par_Ref, Str_2_Par_Ref) +/*************************************************/ + /* executed once */ + /* Str_1_Par_Ref == "DHRYSTONE PROGRAM, 1'ST STRING" */ + /* Str_2_Par_Ref == "DHRYSTONE PROGRAM, 2'ND STRING" */ + +Str_30 Str_1_Par_Ref; +Str_30 Str_2_Par_Ref; +{ + REG One_Thirty Int_Loc; + Capital_Letter Ch_Loc; + + Int_Loc = 2; + while (Int_Loc <= 2) /* loop body executed once */ + if (Func_1 (Str_1_Par_Ref[Int_Loc], + Str_2_Par_Ref[Int_Loc+1]) == Ident_1) + /* then, executed */ + { + Ch_Loc = 'A'; + Int_Loc += 1; + } /* if, while */ + if (Ch_Loc >= 'W' && Ch_Loc < 'Z') + /* then, not executed */ + Int_Loc = 7; + if (Ch_Loc == 'R') + /* then, not executed */ + return (true); + else /* executed */ + { + if (strcmp (Str_1_Par_Ref, Str_2_Par_Ref) > 0) + /* then, not executed */ + { + Int_Loc += 7; + Int_Glob = Int_Loc; + return (true); + } + else /* executed */ + return (false); + } /* if Ch_Loc */ +} /* Func_2 */ + + +Boolean Func_3 (Enum_Par_Val) +/***************************/ + /* executed once */ + /* Enum_Par_Val == Ident_3 */ +Enumeration Enum_Par_Val; +{ + Enumeration Enum_Loc; + + Enum_Loc = Enum_Par_Val; + if (Enum_Loc == Ident_3) + /* then, executed */ + return (true); + else /* not executed */ + return (false); +} /* Func_3 */ + diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/EXPLASM/BYTEDEMO.C b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/EXPLASM/BYTEDEMO.C new file mode 100644 index 0000000..209b4f0 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/EXPLASM/BYTEDEMO.C @@ -0,0 +1,148 @@ +/* Explanation of byte-reversing in ARM assembler + + for PC only (uses cursor control codes) +*/ + +#include + +static void cls() +{ + printf("\033[2J"); +} + +static void up(int n) +{ + while (n > 0) + { printf("\033[1A"); --n; + } +} + +static void pause() +{ + fprintf(stderr, "Please press to proceeed "); + while( fgetc(stdin) != '\n' ); +} + +static void prologue() +{ + printf("\ + AMAZING FACTS ABOUT THE ARM - Reversing the bytes in a word\n\ +\n\ +This function reverses the bytes in a word. The method was discovered in\n\ +1986 following a competition between ARM programmers; it requires just 4\n\ +instructions and 1 work register. A method using only 3 instructions per\n\ +word reversed was also found, but it has some set-up overhead and uses a\n\ +2nd register. Can you re-discover this method?\n\ +\n\ +Later, the C compiler was 'taught' to generate exactly the instructions\n\ +needed, from C source. Check this claim using armcc -S -DREV byterev.c\n\ +and examining the assembly code file produced.\n\ +\n\ +unsigned long reverse(unsigned long v)\n\ +{ unsigned long t;\n\ + t = v ^ ((v << 16) | (v >> 16)); /* EOR r1,r0,r0,ROR #16 */\n\ + t &= ~0xff0000; /* BIC r1,r1,#&ff0000 */\n\ + v = (v << 24) | (v >> 8); /* MOV r0,r0,ROR #8 */\n\ + return v ^ (t >> 8); /* EOR r0,r0,r1,LSR #8 */\n\ +}\n\ +\n\ +To see the method in action, press . Each time you press \n\ +one step of the reversal process will be executed. The values displayed\n\ +are symbolic, starting with the input word D C B A.\n\ +\n"); +} + +static void prelude() +{ + printf("\ + AMAZING FACTS ABOUT THE ARM - Reversing the bytes in a word\n\ +\n\ +unsigned long reverse(unsigned long v)\n\ +{ unsigned long t;\n\ + t = v ^ ((v << 16) | (v >> 16)); /* EOR r1,r0,r0,ROR #16 */\n\ + t &= ~0xff0000; /* BIC r1,r1,#&ff0000 */\n\ + v = (v << 24) | (v >> 8); /* MOV r0,r0,ROR #8 */\n\ + return v ^ (t >> 8); /* EOR r0,r0,r1,LSR #8 */\n\ +}\n\ +\n"); +} + +static void show_state_1() +{ + printf("\ + v / r0 t / r1 original input in v/r0\n\ +\n\ + +---+---+---+---+ +---+---+---+---+\n\ + | D | C | B | A | | x | x | x | x |\n\ + +---+---+---+---+ +---+---+---+---+\n\ +\n\n\n\n\n\n\n"); +} + +static void show_state_2() +{ + printf("\ + v / r0 t / r1 state after executing \n\ +\n\ + +---+---+---+---+ +---+---+---+---+ t = v ^ ((v<<16) | (v>>16));\n\ + | D | C | B | A | |D^B|C^A|B^D|A^C|\n\ + +---+---+---+---+ +---+---+---+---+ EOR r1,r0,r0,ROR #16\n\ +\n\n\n\n\n\n\n"); +} + +static void show_state_3() +{ + printf("\ + +---+---+---+---+ +---+---+---+---+ t &= ~0xff0000; \n\ + | D | C | B | A | |D^B| 0 |B^D|A^C|\n\ + +---+---+---+---+ +---+---+---+---+ BIC r1,r1,#&ff0000 \n\ +\n\n\n\n\n\n\n"); +} + +static void show_state_4() +{ + printf("\ + +---+---+---+---+ +---+---+---+---+ v = (v << 24) | (v >> 8);\n\ + | A | D | C | B | |D^B| 0 |B^D|A^C|\n\ + +---+---+---+---+ +---+---+---+---+ MOV r0,r0,ROR #8 \n\ +\n\n\n\n\n\n\n"); +} + +static void show_state_5() +{ + printf("\ + +---+---+---+---+ +---+---+---+---+ v = v ^ (t >> 8); \n\ +\n\ + +---+-^-+-^-+-^-+---+ +---+---+---+---+ EOR r0,r0,r1,LSR #8\n\ + |D^B| 0 |B^D|A^C|\n\ + +---+---+---+---+\n\ +\n\ + +---+---+---+---+\n\ + | A | B | C | D | (original input was: D C B A)\n\ + +---+---+---+---+\n\ +\n"); +} + +int main() +{ + cls(); + prologue(); + pause(); + cls(); + prelude(); + show_state_1(); + pause(); + up(13); + show_state_2(); + pause(); + up(11); + show_state_3(); + pause(); + up(11); + show_state_4(); + pause(); + up(11); + show_state_5(); + pause(); + fputc('\n', stdout); + return( 0 ); +} diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/EXPLASM/DIVC.C b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/EXPLASM/DIVC.C new file mode 100644 index 0000000..3a5d85c --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/EXPLASM/DIVC.C @@ -0,0 +1,213 @@ +/* Optimal divide-by-contstant code generator + Advanced RISC Machines +*/ + + +#include +#include + +#define BANNER "generated by divc 1.02 (Advanced RISC Machines)" +#define DATE "27 Jan 94" + +#define DIVIDE_BY_2_MINUS_1 0 +#define DIVIDE_BY_2_PLUS_1 1 + + +typedef unsigned int uint; + + +uint log2( uint n ) +{ + uint bit, pow, logn; + + for( bit = 0, pow = 1; bit < 31; bit++, pow <<= 1 ) + { + if( n == pow ) logn = bit; + } + + return( logn ); +} + + +int powerof2( int n ) +{ + return( n == ( n & (-n) ) ); +} + + +void dodiv2m1( uint logd, uint logmsb ) +{ + /* Output instructions to do division by 2^n - 1 */ + printf( "\tMOV a1, a1, lsr #1\n" ); + + while( logd < 32 ) + { + printf( "\tADD a1, a1, a1, lsr #%d\n", logd ); + logd <<= 1; + } + printf( "\tMOV a1, a1, lsr #%d\n", logmsb - 1 ); +} + + +void dodiv2p1( uint logd, uint logmsb ) +{ + /* Output instructions to do division by 2^n + 1 */ + printf( "\tSUB a1, a1, a1, lsr #%d\n", logd ); + + while( logd < 16 ) + { + logd <<= 1; + printf( "\tADD a1, a1, a1, lsr #%d\n", logd ); + } + + printf( "\tMOV a1, a1, lsr #%d\n", logmsb ); +} + + +void loada4( uint type, uint lsb, uint msb ) +{ + /* Constant is too big to be used as an immediate constant, */ + /* so load it into register a4. */ + printf( "\tMOV a4, #0x%x\n", msb ); + + switch( type ) + { + case DIVIDE_BY_2_MINUS_1: + printf( "\tSUB a4, a4, #0x%x\n", lsb ); + break; + + case DIVIDE_BY_2_PLUS_1: + printf( "\tADD a4, a4, #0x%x\n", lsb ); + break; + + default: + fputs( "Internal error", stderr ); + } +} + + +void divideby2( uint type, uint n, uint lsb, uint msb ) +{ + uint loglsb; + uint logmsb; + uint usinga4; + + loglsb = log2( lsb ); + logmsb = log2( msb ); + + printf( "; %s [%s]\n\n", BANNER, DATE ); + printf( "\tAREA |div%d$code|, CODE, READONLY\n\n", n ); + printf( "\tEXPORT udiv%d\n\n", n ); + printf( "udiv%d\n", n ); + printf( "; takes argument in a1\n" ); + printf( "; returns quotient in a1, remainder in a2\n" ); + printf( "; cycles could be saved if only divide or remainder is required\n" ); + + usinga4 = ( n >> loglsb ) > 255; + if( usinga4 ) + { + loada4( type, lsb, msb ); + printf( "\tSUB a2, a1, a4\n" ); + } + else + { + printf( "\tSUB a2, a1, #%d\n", n ); + } + + /* 1/n as a binary number consists of a simple repeating pattern */ + /* The multiply by 1/n is expanded as a sequence of ARM instructions */ + /* (there is a rounding error which must be corrected later) */ + switch( type ) + { + case DIVIDE_BY_2_MINUS_1: + dodiv2m1( logmsb - loglsb, logmsb ); + /* Now do multiply-by-n */ + printf( "\tRSB a3, a1, a1, asl #%d\n", logmsb - loglsb ); + break; + + case DIVIDE_BY_2_PLUS_1: + dodiv2p1( logmsb - loglsb, logmsb ); + /* Now do multiply-by-n */ + printf( "\tADD a3, a1, a1, asl #%d\n", logmsb - loglsb ); + break; + + default: + fputs( "Internal error", stderr ); + } + + /* Subtract from adjusted original to obtain remainder */ + printf( "\tSUBS a2, a2, a3, asl #%d\n", loglsb ); + + /* Apply corrections */ + printf( "\tADDPL a1, a1, #1\n" ); + if( usinga4 ) + { + printf( "\tADDMI a2, a2, a4\n" ); + } + else + { + printf( "\tADDMI a2, a2, #%d\n", n ); + } + + /* Additional test required for divide-by-3, as result could be */ + /* off by 2 lsb due to accumulated rounding errors. */ + if( n == 3 ) + { + printf( "\tCMP a2, #3\n" ); + printf( "\tADDGE a1, a1, #1\n" ); + printf( "\tSUBGE a2, a2, #3\n" ); + } + + printf( "\tMOV pc, lr\n\n" ); + printf( "\tEND\n" ); +} + + +int main( int argc, char *argv[] ) +{ + if( argc != 2 ) + { + printf( "Usage: divc \n" ); + printf( "Generates optimal ARM code for divide-by-constant\n" ); + printf( "where is one of (2^n-2^m) or (2^n+2^m) eg. 10\n" ); + printf( "Advanced RISC Machines [%s]\n", DATE ); + } + else + { + int num; + + num = atoi( argv[ 1 ] ); + if( num <= 1 ) + { + fprintf( stderr, "%d is not sensible\n", num ); + } + else + { + uint lsb = 1; + + /* find least-significant bit */ + while( ( num & lsb ) == 0 ) + { + lsb <<= 1; + } + + if( powerof2( num ) ) + { + fprintf( stderr, "%d is an easy case\n", num ); + } + else if( powerof2( num + lsb ) ) + { + divideby2( DIVIDE_BY_2_MINUS_1, num, lsb, num + lsb ); + } + else if( powerof2( num - lsb ) ) + { + divideby2( DIVIDE_BY_2_PLUS_1, num, lsb, num - lsb ); + } + else + { + fprintf( stderr, "%d is not one of (2^n-2^m) or (2^n+2^m)\n", num ); + } + } + } + return( 0 ); +} diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/EXPLASM/RANDOM.S b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/EXPLASM/RANDOM.S new file mode 100644 index 0000000..67aacdf --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/EXPLASM/RANDOM.S @@ -0,0 +1,42 @@ +; Random number generator +; +; This uses a 33-bit feedback shift register to generate a pseudo-randomly +; ordered sequence of numbers which repeats in a cycle of length 2^33 - 1 +; NOTE: randomseed should not be set to 0, otherwise a zero will be generated +; continuously (not particularly random!). +; +; This is a good application of direct ARM assembler, because the 33-bit +; shift register can be implemented using RRX (which uses reg + carry). +; An ANSI C version would be less efficient as the compiler would not use RRX. + + AREA |Random$$code|, CODE, READONLY + + EXPORT randomnumber + +randomnumber +; on exit: +; a1 = low 32-bits of pseudo-random number +; a2 = high bit (if you want to know it) + LDR ip, |seedpointer| + LDMIA ip, {a1, a2} + TST a2, a2, LSR#1 ; to bit into carry + MOVS a3, a1, RRX ; 33-bit rotate right + ADC a2, a2, a2 ; carry into LSB of a2 + EOR a3, a3, a1, LSL#12 ; (involved!) + EOR a1, a3, a3, LSR#20 ; (similarly involved!) + STMIA ip, {a1, a2} + + MOV pc, lr + +|seedpointer| + DCD seed + + + AREA |Random$$data|, DATA + + EXPORT seed +seed + DCD &55555555 + DCD &55555555 + + END diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/EXPLASM/RANDTEST.C b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/EXPLASM/RANDTEST.C new file mode 100644 index 0000000..092ffb4 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/EXPLASM/RANDTEST.C @@ -0,0 +1,20 @@ +/* Random number generator demo program + + Calls assembler function 'randomnumber' defined in random.s +*/ + +#include + +/* this function prototype is needed because 'randomnumber' is external */ +extern unsigned int randomnumber( void ); + +int main() +{ + int loop; + + for( loop = 0; loop < 10; loop++ ) + { printf( "randomnumber() returned %08x\n", randomnumber() ); + } + + return( 0 ); +} diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/EXPLASM/RANTEST.APJ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/EXPLASM/RANTEST.APJ new file mode 100644 index 0000000..e8bde34 Binary files /dev/null and b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/EXPLASM/RANTEST.APJ differ diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/EXPLASM/UDIV10.S b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/EXPLASM/UDIV10.S new file mode 100644 index 0000000..787bb0b --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/EXPLASM/UDIV10.S @@ -0,0 +1,23 @@ +; generated by divc 1.01 (Advanced RISC Machines) [01 Jul 92] + + AREA |div10$code|, CODE, READONLY + + EXPORT udiv10 + +udiv10 +; takes argument in a1 +; returns quotient in a1, remainder in a2 +; cycles could be saved if only divide or remainder is required + SUB a2, a1, #10 + SUB a1, a1, a1, lsr #2 + ADD a1, a1, a1, lsr #4 + ADD a1, a1, a1, lsr #8 + ADD a1, a1, a1, lsr #16 + MOV a1, a1, lsr #3 + ADD a3, a1, a1, asl #2 + SUBS a2, a2, a3, asl #1 + ADDPL a1, a1, #1 + ADDMI a2, a2, #10 + MOV pc, lr + + END diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/EXPLASM/UTOA.APJ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/EXPLASM/UTOA.APJ new file mode 100644 index 0000000..b4ea8b8 Binary files /dev/null and b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/EXPLASM/UTOA.APJ differ diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/EXPLASM/UTOA1.S b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/EXPLASM/UTOA1.S new file mode 100644 index 0000000..369773a --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/EXPLASM/UTOA1.S @@ -0,0 +1,60 @@ +; This demonstrates recursion in ARM assembler. +; this version does not perform stack checking. +; +; Converting a number to a string can be expressed using a divide-and- +; conquer algorithm: +; = "" + + AREA |utoa$$code|, CODE, READONLY + + EXPORT dtoa + EXPORT utoa + + IMPORT udiv10 + +dtoa +; converts signed word to string +; a1 = char *buffer +; a2 = signed int number +; on exit: +; a1 = char *end_of_string + + CMP a2, #0 + RSBMI a2, a2, #0; make a2 positive + MOVMI ip, #'-' + STRMIB ip, [ a1 ], #1 ; add minus sign to buffer + +; *** intentional drop-through to utoa *** + +utoa +; recursive routine to convert unsigned word to string +; on entry: +; a1 = char *buffer +; a2 = unsigned int number +; on exit: +; a1 = char *end_of_string ; character after last digit +; all other registers preserved + + STMFD sp!, {v1, v2, lr} ; save 2 variable registers and + ; the return address + + MOV v1, a1 ; keep char *buffer for later + MOV v2, a2 ; and keep the number for later + MOV a1, a2 + BL udiv10 ; on return, the quotient is in a1 + + SUB v2, v2, a1, LSL #3 ; number - 8*quoitient + SUB v2, v2, a1, LSL #1 ; - 2*quotient = remainder + + CMP a1, #0 ; quotient non-zero? + MOVNE a2, a1 ; quotient to a2... + MOV a1, v1 ; buffer pointer unconditionally to a1 + BLNE utoa ; conditional recursive call to utoa + + ADD v2, v2, #'0' ; final digit + STRB v2, [a1], #1 ; store digit at end of buffer + + LDMFD sp!, {v1, v2, pc} ; restore and return + + END + diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/EXPLASM/UTOATEST.C b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/EXPLASM/UTOATEST.C new file mode 100644 index 0000000..5e411b5 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/EXPLASM/UTOATEST.C @@ -0,0 +1,22 @@ +/* test utoa or utoa */ + +#include + +extern char *utoa( char *string, signed int num ); + +int main() +{ + signed int num; + char buffer[ 12 ]; + + puts( "Enter number:" ); + + if( scanf( "%d", &num ) == 1 ) + { + *utoa( buffer, num ) = 0; /* add string terminator */ + puts( "utoa yields:" ); + puts( buffer ); + } + + return( 0 ); +} diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/OVERLAY/GETDATA.C b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/OVERLAY/GETDATA.C new file mode 100644 index 0000000..b0e5a36 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/OVERLAY/GETDATA.C @@ -0,0 +1,17 @@ +#include + +int getData(char *buffer,int length) +{ + int charsIn; + int charRead; + charsIn=0; + for (charsIn=0;charsIn +#include +#define INBUFFSIZE 192 +#define OUTBUFFSIZE 257 + +static char inBuff[INBUFFSIZE]; +static char outBuff[OUTBUFFSIZE]; +static int charCount=0; + +extern int getData(char *,int); +extern int uuencode(char *, char *, int); +extern int _sys_flen(int ); +extern int _sys_open(char *,int ); +extern int _sys_read(int, void *, int, int ); +extern int _sys_close(int); + +int main(int argc,char **argv) +{ + int uuCount; + charCount = getData(inBuff,sizeof(inBuff)); + if (charCount<0) { + fprintf(stderr,"Error reading data.\n"); + } + else { + uuCount=uuencode(inBuff,outBuff,charCount); + outBuff[uuCount]='\0'; + puts(outBuff); + } + return 0; +} + +void MemCopy(void *d,void *s,int c) +{ + memmove(d,s,c); +} + +int LoadOverlaySegment(int nameLen,char *name,void *baseAdr) +{ + char name0[16]; + int length; + int fh; + + memmove(name0,name,nameLen); + name0[nameLen]='\0'; +#define OPEN_B 1 +#define OPEN_R 0 + + fh = _sys_open(name0,OPEN_B|OPEN_R); + if (fh==0) return 0; + length = _sys_flen(fh); + (void)_sys_read(fh,baseAdr,length,0); + (void)_sys_close(fh); + return length; +} + diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/OVERLAY/MAININIT.S b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/OVERLAY/MAININIT.S new file mode 100644 index 0000000..41220ea --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/OVERLAY/MAININIT.S @@ -0,0 +1,9 @@ + AREA MainWithOverlayInit, CODE, READONLY + IMPORT |Image$$overlay_init| + IMPORT __main + + ENTRY + BL |Image$$overlay_init| + BL __main + END + diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/OVERLAY/MAKEFILE b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/OVERLAY/MAKEFILE new file mode 100644 index 0000000..fcf6760 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/OVERLAY/MAKEFILE @@ -0,0 +1,27 @@ +LIB= + +.c.o: + armcc -bi -c -APCS 3/32/noswst $< + +.s.o: + armasm -bi -APCS 3/32/noswst $< + +all: ov/root +ov/root: main.o uue.o getdata.o overmgrs.o maininit.o startup.o + armlink -bin -base 0x40000 -data 0x10000 -ov ovlist \ + -o ov maininit.o startup.o main.o overmgrs.o uue.o getdata.o \ + -FIRST maininit.o ${LIB}/armlib.32b -map -symbols - -list tS.map \ + -v + +startup.o: startup.s + +overmgrs.o: overmgrs.s + +maininit.o: maininit.s + +main.o: main.c + +uue.o: uue.c + +getdata.o: getdata.c + diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/OVERLAY/OVERMGRS.S b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/OVERLAY/OVERMGRS.S new file mode 100644 index 0000000..4aeb6e4 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/OVERLAY/OVERMGRS.S @@ -0,0 +1,391 @@ +; AUTHORS: L.Smith, J. Sutton +; +; DATE: Last edit 16-Mar-90 (ECN) +; +; VERSION: 0.07 +; +; DESCRIPTION: Overlay Manager +; +; CHANGES: 28-Feb-90 LDS +; Fixed a bug in check_for_invalidated_returns whereby a return +; handler was allocated on return rather than just on call. +; +; 16-Mar-90 ECN +; Use OS_GetEnv to read the overlay directory instead of Obey$Dir +; which doesn't work if the image is not executed from an obey file. +; +; Tidied up the behaviour of "Disk not present errors". The previous +; version just splatted a message all over the desktop. The new +; version only prompt for disk insertion if executing outside the +; desktop (inside the desktop the wimp will prompt the user). +; +; Tidied up the generation of errors and exit from application. +; Previously either gave a trap or stiffed the machine. +; +;;; Copyright (C) Advanced RISC Machines Ltd., 1991 + + EXPORT |Image$$overlay_init| + EXPORT |Image$$load_seg| + +; pointers to start and end of workspace area supplied by the linker + IMPORT |Overlay$$Data$$Base| + IMPORT |Overlay$$Data$$Limit| + IMPORT |Image$$RO$$Limit| + IMPORT |Image$$RW$$Base| + IMPORT |Image$$ZI$$Base| + IMPORT MemCopy + IMPORT LoadOverlaySegment + IMPORT SevereErrorHandler, WEAK + +ZeroInitCodeOffset EQU 64 + +; Why does the linker need to generate this zero init area, why can't the +; Overlay Manager define it itself??? ECN. +; +; Layout of workspace allocated by the linker pointed to by Overlay$$Data +; This area is automatically zero-initialised AFTER overlay_init is called +; offsets are prefixed with Work_ + ^ 0 +Work_HStack # 4 ; top of stack of allocated handlers +Work_HFree # 4 ; head of free-list +Work_RSave # 9*4 ; for R0-R8 +Work_LRSave # 4 ; saved lr +Work_PCSave # 4 ; saved PC +Work_PSRSave # 4 ; saved CPSR +Work_ReturnHandlersArea EQU @ ; rest of this memory is treated as heap + ; space for the return handlers +Work_MinSize EQU @ + 32 * RHandl_Size + +; Return handler. 1 is allocated per inter-segment procedure call +; allocated and free lists of handlers are pointed to from HStack and HFree +; offsets are prefixed with RHandl_ + ^ 0 +RHandl_Branch # 4 ; BL load_seg_and_ret +RHandl_RealLR # 4 ; space for the real return address +RHandl_Segment # 4 ; -> PCIT section of segment to load +RHandl_Link # 4 ; -> next in stack order +RHandl_Size EQU @ + +; set up by check_for_invalidated_returns. + +; PCITSection. 1 per segment stored in root segment, allocated by linker +; offsets are prefixed with PCITSect_ + ^ 0 +PCITSect_Vecsize # 4 ; .-4-EntryV ; size of entry vector +PCITSect_Base # 4 ; used by load_segment; not initialised +PCITSect_Limit # 4 ; used by load_segment; not initialised +PCITSect_Name # 11 ; <11 bytes> ; 10-char segment name + NUL in 11 bytes +PCITSect_Flags # 1 ; ...and a flag byte +PCITSect_ClashSz # 4 ; PCITEnd-.-4 ; size of table following +PCITSect_Clashes # 4 ; >table of pointers to clashing segments + +; Stack structure (all offsets are negative) +; defined in procedure call standard +; offsets are prefixed with Stack_ + ^ 0 +Stack_SaveMask # -4 +Stack_LRReturn # -4 +Stack_SPReturn # -4 +Stack_FPReturn # -4 + +; the code and private workspace area + AREA OverLayMgrArea, PIC, CODE , READONLY + +STRLR STR lr, [pc, #-8] ; a word that is to be matched in PCITs + +; Store 2 words which are the addresses of the start and end of the workspace +WorkSpace DCD |Overlay$$Data$$Base| +WorkSpaceEnd DCD |Overlay$$Data$$Limit| +InitFlag DCD InitDoneFlag + +|Image$$overlay_init| ROUT +; Initialise overlay manager. +; In the AIF format this is is called from offset 8 in header. This routine has +; to pass control to the zero initialisation code. +; In Non AIF formats this routine has to be called explicitly e.g. from +; a customised rtstand.s . +; +; In the AIF example the entire root segment is copied to the load address. +; +; In the non AIF example only the RW part of the root is copied. +; + LDR ip,WorkSpace + IF :DEF:AIF_EXAMPLE + STR lr,[ip,#Work_LRSave] + + ADD ip,ip,#Work_RSave + STMIA ip,{r0-r3} + +; +; Look at the AIF header and add compute the total size of the AIF header +; + SUB r1,lr,#0xC + + LDR r0,[r1,#0x28] + + LDR r2,[r1,#0x14] + LDR r3,[r1,#0x18] + ADD r2,r2,r3 + LDR r3,[r1,#0x1C] + ADD r2,r2,r3 + +; +; A system specific Memory Copy call. r0 is the destination area. +; r1 is the source area. +; r2 is the block size in bytes. +; + BL MemCopy + LDR ip,WorkSpace + LDR lr,[ip,#Work_LRSave] + ADD ip,ip,#Work_RSave + SUB lr,lr,#12 + LDR lr,[lr,#0x28] + ADD lr,lr,#12 + LDMIA ip,{r0-r3} +; +; Return to the Zero Initialisation Code in the AIF header. +; + ADD pc,lr,#ZeroInitCodeOffset-12 + ELSE + LDR ip,WorkSpace + ADD ip,ip,#Work_RSave + STMIA ip,{r0-r2,lr} + + LDR r0,=|Image$$RW$$Base| + LDR r1,=|Image$$RO$$Limit| + LDR r2,=|Image$$ZI$$Base| + SUB r2,r2,r0 + BL MemCopy + + LDR ip,WorkSpace + ADD ip,ip,#Work_RSave + LDMIA ip,{r0-r2,PC} + ENDIF + + DCD 0 ; Not needed for a real system but needed when using ARMSD + ; is used to simulate a ROMN based system. +; entry point +|Image$$load_seg| ROUT +; called when segment has been called but is not loaded +; presume ip is corruptible by this + LDR ip, WorkSpace + ADD ip, ip, #Work_RSave + STMIA ip, {r0-r8} ; save working registers + MRS r4, CPSR ; Save status register -it'll get stored in the + ; workspace later. +; (save in my workspace because stack is untouchable during procedure call) + LDR r0, InitFlag + LDRB r1, [r0] + CMP r1, #0 + BNE InitDone + +;Initialise Return Handlers on first call to this routine + MOV r1, #1 + STRB r1, [r0] ; set InitDone flag + LDR r0, WorkSpace +; r0 points to workspace +; corrupts r0-r3,lr +; create and initialise return handler linked list + MOV r2, #0 + STR r2, [r0, #Work_HStack] ; initialise start of handler list with NULL + ADD r1, r0, #Work_ReturnHandlersArea ; Start of heap space + STR r1, [r0, #Work_HFree] ; Start of list of free handlers point to heap space + LDR r0, WorkSpaceEnd ; for test in loop to make sure.. + SUBS r0, r0, #RHandl_Size ; ..I dont overrun in init +01 ADD r3, r1, #RHandl_Size ; next handler +; set up link to point to next handler (in fact consecutive locations) + STR r3, [r1, #RHandl_Link] + MOV r1, r3 ; next handler + CMP r1, r0 ; test for end of workspace + BLT %BT01 + SUB r1, r1, #RHandl_Size ; previous handler + STR r2, [r1, #RHandl_Link] ; NULL-terminate list + +InitDone + LDR r3, WorkSpace + STR r4, [r3, #Work_PSRSave] ; CPSR read into R4 before the InitDone + ; test. + MOV r8,lr ; + LDR r0, [r8, #-8] ; saved r14... (is end of PCIT) + STR r0, [r3, #Work_LRSave] ; ...save it here ready for retry + LDR r0, STRLR ; look for this... + SUB r1, r8, #8 ; ... starting at last overwrite +01 LDR r2, [r1, #-4]! + CMP r2, r0 ; must stop on guard word... + BNE %B01 + ADD r1, r1, #4 ; gone one too far... + STR r1, [r3, #Work_PCSave] ; where to resume at + +load_segment + +; ip -> the register save area; r8 -> the PCIT section of the segment to load. +; First re-initialise the PCIT section (if any) which clashes with this one... + + ADD r1, r8, #PCITSect_Clashes + LDR r0, [r8, #PCITSect_ClashSz] +01 SUBS r0, r0, #4 + BLT Done_Reinit ; nothing left to do + LDR r7, [r1], #4 ; a clashing segment... + LDRB r2, [r7, #PCITSect_Flags] ; its flags (0 if unloaded) + CMPS r2, #0 ; is it loaded? + BEQ %B01 ; no, so look again + +; clashing segment is loaded (clearly, there can only be 1 such segment) +; mark it as unloaded and reinitialise its PCIT +; r7 -> PCITSection of clashing loaded segment + + MOV r0, #0 + STRB r0, [r7, #PCITSect_Flags] ; mark as unloaded + LDR r0, [r7, #PCITSect_Vecsize] + SUB r1, r7, #4 ; end of vector + LDR r2, STRLR ; init value to store in the vector... +02 STR r2, [r1, #-4]! ;> + SUBS r0, r0, #4 ;> loop to initialise the PCIT segment + BGT %B02 ;> +; Now we check the chain of call frames on the stack for return addresses + +; which have been invalidated by loading this segment and install handlers +; for each invalidated return. +; Note: r8 identifies the segment being loaded; r7 the segment being unloaded. + + BL check_for_invalidated_returns +Done_Reinit + +; All segment clashes have now been dealt with, as have the re-setting +; of the segment-loaded flags and the intercepting of invalidated returns. +; So, now load the required segment. + +Retry +; +; Call a routine to load the overlay segment. +; First parameter is the length of the segment name. +; The second parameter is the address of the segment name +; The third parameter is the base address of the segement. +; The routine returns the segment length in r0. +; + MOV r0,#12 + ADD r1, r8, #PCITSect_Name + LDR r2, [ r8, #PCITSect_Base] + BL LoadOverlaySegment + + TEQ r0,#0 + MOVEQ r0,#2 + BEQ SevereErrorHandler + + LDR ip,WorkSpace + ADD ip,ip,#Work_RSave +; +; Mark the segment as loaded. +; + MOV r1,#1 + STRB r1, [r8, #PCITSect_Flags] + + LDR r2, [r8, #PCITSect_Base] + ADD r0, r2, r0 ; start + length = end of file + +; The segment's entry vector is at the end of the segment... +; ...copy it to the PCIT section identified by r8. + + LDR r1, [r8, #PCITSect_Vecsize] + SUB r3, r8, #8 ; end of entry vector... + MOV r4, #0 ; for data initialisation +01 LDR r2, [r0, #-4]! ;>loop to copy + STR r4, [r0] ; (zero-init possible data section) + STR r2, [r3], #-4 ;>the segment's PCIT + SUBS r1, r1, #4 ;>section into the + BGT %B01 ;>global PCIT + +; Finally, continue, unabashed... + + LDR r3, WorkSpace + LDR r3, [r3,#Work_PSRSave] + MSR CPSR,r3 + + LDMIA ip, {r0-r8, lr, pc} + +load_seg_and_ret +; presume ip is corruptible by this + LDR ip, WorkSpace + ADD ip, ip, #Work_RSave + STMIA ip, {r0-r8} ; save working registers +; (save in my workspace because stack is untouchable during procedure call) + LDR r3, WorkSpace + MRS r8, CPSR + STR r8, [r3, #Work_PSRSave] + +; lr points to the return handler + MOV r8, lr + ; load return handler fields RealLR, Segment, Link + LDMIA r8, {r0, r1, r2} + SUB r8, r8, #4 ; point to true start of return handler before BL + STR r0, [r3, #Work_LRSave] + STR r0, [r3, #Work_PCSave] +; Now unchain the handler and return it to the free pool +; HStack points to this handler + LDR r0, [r3, #Work_HStack] + CMPS r0, r8 + MOVNE r0, #1 + BNE SevereErrorHandler + STR r2, [r3, #Work_HStack] ; new top of handler stack + LDR r2, [r3, #Work_HFree] + STR r2, [r8, #RHandl_Link] ; Link -> old HFree + STR r8, [r3, #Work_HFree] ; new free list + MOV r8, r1 ; segment to load + B load_segment + +check_for_invalidated_returns +; Note: r8 identifies the segment being loaded; r7 the segment being unloaded. +; Note: check for returns invalidated by a call NOT for returns invalidated by +; a return! In the 2nd case, the saved LR and saved PC are identical. + LDR r5, WorkSpace + ADD r6, r5, #Work_LRSave ; 1st location to check + LDMIA r6, {r0, r1} ; saved LR & PC + CMPS r0, r1 + MOVEQ pc, lr ; identical => returning... + MOV r0, fp ; temporary FP... +01 LDR r1, [r6] ; the saved return address... + LDR r2, [r5, #Work_HStack] ; top of handler stack + CMPS r1, r2 ; found the most recent handler, so + MOVEQ pc, lr ; abort the search + LDR r2, [r7, #PCITSect_Base] + CMPS r1, r2 ; see if >= base... + BLT %F02 + LDR r2, [r7, #PCITSect_Limit] + CMPS r1, r2 ; ...and < limit ? + BLT FoundClash +02 CMPS r0, #0 ; bottom of stack? + MOVEQ pc, lr ; yes => return + ADD r6, r0, #Stack_LRReturn + LDR r0, [r0, #Stack_FPReturn] ; previous FP + B %B01 +FoundClash + LDR r0, [r5, #Work_HFree] ; head of chain of free handlers + CMPS r0, #0 + MOVEQ r0, #2 + BEQ SevereErrorHandler +; Transfer the next free handler to head of the handler stack. + LDR r1, [r0, #RHandl_Link] ; next free handler + STR r1, [r5, #Work_HFree] + LDR r1, [r5, #Work_HStack] ; the active handler stack + STR r1, [r0, #RHandl_Link] + STR r0, [r5, #Work_HStack] ; now with the latest handler linked in +; Initialise the handler with a BL load_seg_and_ret, RealLR and Segment. + ADR r1, load_seg_and_ret + SUB r1, r1, r0 ; byte offset for BL in handler + SUB r1, r1, #8 ; correct for PC off by 8 + MOV r1, r1, ASR #2 ; word offset + BIC r1, r1, #&FF000000 + ORR r1, r1, #&EB000000 ; code for BL + STR r1, [r0, #RHandl_Branch] + + LDR r1, [r6] ; LRReturn on stack + STR r1, [r0, #RHandl_RealLR] ; RealLR + STR r0, [r6] ; patch stack to return to handler + + STR r7, [r0, #RHandl_Segment] ; segment to re-load on return + MOV pc, lr ; and return + + AREA OverlayInit, DATA +InitDoneFlag DCD 0 + + END diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/OVERLAY/OVLIST b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/OVERLAY/OVLIST new file mode 100644 index 0000000..c04b8b5 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/OVERLAY/OVLIST @@ -0,0 +1,2 @@ +bert(0x9000) uue.o +fred(0x9000) getdata.o diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/OVERLAY/STARTUP.S b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/OVERLAY/STARTUP.S new file mode 100644 index 0000000..b61472a --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/OVERLAY/STARTUP.S @@ -0,0 +1,52 @@ + AREA |!!!|, CODE, READONLY + + IMPORT __entry ; The C library entry point + + EXPORT __main + + IMPORT |Image$$RO$$Base| + IMPORT |Image$$RO$$Limit| + IMPORT |Image$$RW$$Base| + IMPORT |Image$$RW$$Limit| + IMPORT |Image$$ZI$$Base| + IMPORT |Image$$ZI$$Limit| + +;----------------------------------------------------------------------------; +; The above symbols are created by the linker to define various sections in ; +; the ROM/RAM image. ; +; ; +; Image$$RO$$Base defines the code (ROM) base address ; +; Image$$RO$$Limit defines the code limit and the start of a section of ; +; data initialisation values which are copied to RAM ; +; in __main below before main is called. ; +; Image$$RW$$Base defines the data (RAM) base address ; +; Image$$RW$$Limit defines the data end address ; +; Image$$ZI$$Base defines the base of a section to be initialised with 0s ; +; Image$$ZI$$Limit defines the end of the region to be initialised with 0s ; +; (must be the same as Image$$RW$$Limit in this model) ; +;----------------------------------------------------------------------------; + +; Code is enter in ARM mode + [ {CONFIG} = 16 + CODE32 + ] + +__main + LDR r0, =|Image$$RO$$Limit| ; Get pointer to ROM data + LDR r1, =|Image$$RW$$Base| ; and RAM copy + LDR r3, =|Image$$ZI$$Base| ; Zero init base => top of initialised data + CMP r0, r1 ; Check that they are different + BEQ %FT1 +0 CMP r1, r3 ; Copy init data + LDRCC r2, [r0], #4 + STRCC r2, [r1], #4 + BCC %BT0 +1 LDR r1, =|Image$$ZI$$Limit| ; Top of zero init segment + MOV r2, #0 +2 CMP r3, r1 ; Zero init + STRCC r2, [r3], #4 + BCC %BT2 + + B __entry + + END diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/OVERLAY/TEXT.TXT b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/OVERLAY/TEXT.TXT new file mode 100644 index 0000000..f304e9a --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/OVERLAY/TEXT.TXT @@ -0,0 +1,742 @@ +Application Note: Use Of Overlays in A ROM Based System + +Version 0.4 May 1995 Laurence Bond + +Introduction +------------ + +This application note describes an example which uses overlays in a ROM based +system. The linker section in the Software Development Toolkit manual should +read in conjunction with this note. + +Please note that this example will only work with Tools 200 alpha-1 or later. + +Example Application Structure +----------------------------- +The overlay root segment code is to be ROM resident. The read-write data will +be RAM resident when the application is running. The two areas are assumed to +be mapped into ROM memory in the same manner as a BIN file produced by the +linker. That is the ROM image of the root segment is: + read-only code + read-only data + read-write code + read-write data + initialised data + zero initialised data + +The areas are assumed to be contiguous. + +When the overlay manager is initialised the read-write areas should be copied +from the ROM to the RAM. + +Example Memory Structure +------------------------ +In this example the memory is assumed to have the following structure + SRAM at addresses 0x8000 up to 0x18000. + ROM starting at the address 0x40000. + +Overlay Manager +--------------- +The linker does not provide the overlay manager. The overlay manager is user +supplied code which controls the overlay mechanism. The linker produces the +appropriate binary files and constructs the PCITs (Procedure Call Indirection +Tables). +The overlay manager must define two publicly visible symbols +Image$$overlay_init and Image$$load_seg. + +Image$$overlay_init is used to initialise the overlay manager. In an AIF based +environment, this routine is called from the Debug/Zero Initialisation slot in +the AIF header. When the overlay manager has been initialised, control should +be passed to the Zero Initialisation code. In non AIF systems, +Image$$overlay_init does not get called automatically. However it should be +called just after the application has been entered. This is the case used in the +example. + +Image$$load_seg is the procedure that performs the functions of the overlay +manager described in the Software Development toolkit manual. + +The overlay manager listed in Appendix A is a modified version of that supplied +with the toolkit. It has been modified to be more operating system independent +and to run in 32 bit mode. The code area has also been made read-only. The flag +used to indicate whether the overlay manager has initialised its workspace has +been moved to a read-write area of its own. + +To aid operating system independence, three routines may be called by the +overlay manager. These could have replaced by inline code. However to aid +clarity, this has not been done. The routines are: + + MemCopy + r0 - Destination address + r1 - Source Address + r2 - Block length in bytes + + This routine does not return anything. + + LoadOverlaySegment + r0 - Length of overlay segment name. + r1 - Overlay segment name address + r2 - Address at which the overlay segment is to be written. + + Returns the number of bytes copied. If this is zero it is treated + as an error. + + SevereErrorHandler + r0 - A value indicating which error condition has occurred. + + This symbol is a weak reference and need not be resolved. In the example + no such routine is provided. However in a real application one should be + provided. + +Linker Symbols +-------------- +The overlay manager relies on the following linker generated symbols: + Image$$RW$$Base Base address of the read-write area + Image$$RO$$Limit Address one byte beyond read-only area + Image$$ZI$$Limit Address one byte beyond the Zero Initialised + data area. + +A Pitfall In Using The C library +-------------------------------- +In this example, a the C library was found to interfere with loaded segments. +The reason is that in the default C library, the C heap is initialised to start +at the address Image$$RW$$Limit. + +For example, the segments could get corrupted by use of the standard C memory +allocation package if they are located to an address greater that this. A malloc +could grab some memory from the heap which just happened to be part of an +overlayed segments code. Similarly loading an overlay segment could result in +the segment data being loaded into an area used by the heap, thereby corrupting +the heap. + + +The Example Application +----------------------- +The example application reads a sequence of characters, terminated either by +end of file or a newline, from stdin. These characters are then UU encoded and +output to stdout. + +The application consists of three C source files and two assembler files +excluding the overlay manager. The C files are as follows: + + getdata.c + This defines a function, getData, which reads the characters into a + buffer passed to it by the main program. + + uue.c + This defines a function, uue, which takes an input buffer passed + in by the main program and writes the UU encoded equivalent into + another buffer supplied by the main program. + + main.c + This contains the C main program and example implementations of + the functions LoadOverlaySegment and MemCopy needed by the overlay + manager. Two statically allocated data buffers are also defined. + + The main program calls getData to read data into a buffer. This buffer + is then passed to uue as the input buffer. The output buffer is zero + terminated after uue returns and the results written to stdout. + + MemCopy is just a call to memmove - a standard C library function. + + LoadOverlaySegment does not use stdio because of the pitfall + mentioned above. Low level calls are used to read the + file contents. The files are assumed to be in the current directory. + + It is straight forward to modify the example to have the overlays + in memory and to copy them to the appropriate locations. This was + not done in this application note because it was felt that little + information would be added by doing so. + +Together with the overlay manager these C files could define the whole +application. Using a BIN file means that further work is necessary. In +particular the overlay manager initialisation routine has to be called somehow. +This requires that the program entry point has to be changed. In this example, +the C library source file startup.s has been modified to eliminate the ENTRY +directive. In a customised environment, the ENTRY directive should be removed +from rtstand.s. + +Now a new entry point is required. This supplied by the file maininit.s . +The file consists of an ENTRY directive and a call to Image$$overlay_init. +Then the code branches to __main the standard C startup routine. + +The source code except for the overlay manager and the modified C __main +function can be found in Appendix B. + +The buffers defined in main.c will be read-write data in the root segment. The +assembler entry point code, the functions defined in main.c and any C library +functions extracted from the library will be in the root segment. + +The function uue will be in an overlay segment named seg1. The function getData +will be in an overlay segment named seg2. + +Testing The Application +----------------------- +The application was built big endian and linked with the following linker +options: + armlink -bin -base 0x40000 -data 0x10000 -ov ovlist \ + -o ov maininit.o startup.o main.o overmgr.o uue.o \ + getdata.o -first maininit.o $(LIB) -map -symbols - \ + -list tS.map -v + +This command produces a plain binary file for the root segment. The overlay +segments are always plain binary files. Both the overlay segments and the +root segment will be be placed in the ov subdirectory whoch should exist before +the command is executed. + +The full Makefile can be found in Appendix B. + +These base the read-only areas at address 0x40000 and the read-write areas at +0x10000. The file ov specifies where the overlay segments are to be placed. +The overlay segments in this example were placed at 0x9000. So the file used +was: + + seg1(0x9000) uue.o + seg2(0x9000) getdata.o + +This uses the modified overlay file format introduced in Tools 200 Alpha-1. + +The application was the loaded into ARMSD. As it was not an AIF file, the +loading process was done manually. +Change the current directory to be the ov directory. + + armsd -bi + armsd: get root 0x40000 + armsd: let pc=0x40000 + +The entry point is at 0x40000 by virtue of the -FIRST option on the linker and +the code structure in startup.s + +After typing 'go' at armsd, the program will wait for the user to type a +newline terminated string. + + armsd: go + Hello World + 2&5L;&\@5V]R;&0* + +This is correct when compared against UUENCODE on SunOS 4.1.3. Note that +initial encoded count byte is not output. + + Program terminated normally at PC = 0x00040248 + 0x00040248: 0xef000011 .... : swi 0x11 + armsd: q + Quitting + +Appendix A +---------- +Overlay Manager Code - overmgr.s +-------------------------------- + +;;; Copyright (C) Advanced RISC Machines Ltd., 1991 + + EXPORT |Image$$overlay_init| + EXPORT |Image$$load_seg| + +; pointers to start and end of workspace area supplied by the linker + IMPORT |Overlay$$Data$$Base| + IMPORT |Overlay$$Data$$Limit| + IMPORT |Image$$RO$$Limit| + IMPORT |Image$$RW$$Base| + IMPORT |Image$$ZI$$Limit| + IMPORT MemCopy + IMPORT LoadOverlaySegment + IMPORT SevereErrorHandler, WEAK + +ZeroInitCodeOffset EQU 64 + +; Layout of workspace allocated by the linker pointed to by Overlay$$Data +; This area is automatically zero-initialised AFTER overlay_init is called +; offsets are prefixed with Work_ + ^ 0 +Work_HStack # 4 ; top of stack of allocated handlers +Work_HFree # 4 ; head of free-list +Work_RSave # 9*4 ; for R0-R8 +Work_LRSave # 4 ; saved lr +Work_PCSave # 4 ; saved PC +Work_PSRSave # 4 ; saved CPSR +Work_ReturnHandlersArea EQU @ ; rest of this memory is treated as heap + ; space for the return handlers +Work_MinSize EQU @ + 32 * RHandl_Size + +; Return handler. 1 is allocated per inter-segment procedure call +; allocated and free lists of handlers are pointed to from HStack and HFree +; offsets are prefixed with RHandl_ + ^ 0 +RHandl_Branch # 4 ; BL load_seg_and_ret +RHandl_RealLR # 4 ; space for the real return address +RHandl_Segment # 4 ; -> PCIT section of segment to load +RHandl_Link # 4 ; -> next in stack order +RHandl_Size EQU @ + +; set up by check_for_invalidated_returns. + +; PCITSection. 1 per segment stored in root segment, allocated by linker +; offsets are prefixed with PCITSect_ + ^ 0 +PCITSect_Vecsize # 4 ; .-4-EntryV ; size of entry vector +PCITSect_Base # 4 ; used by load_segment; not initialised +PCITSect_Limit # 4 ; used by load_segment; not initialised +PCITSect_Name # 11 ; <11 bytes> ; 10-char segment name + NUL in 11 bytes +PCITSect_Flags # 1 ; ...and a flag byte +PCITSect_ClashSz # 4 ; PCITEnd-.-4 ; size of table following +PCITSect_Clashes # 4 ; >table of pointers to clashing segments + +; Stack structure (all offsets are negative) +; defined in procedure call standard +; offsets are prefixed with Stack_ + ^ 0 +Stack_SaveMask # -4 +Stack_LRReturn # -4 +Stack_SPReturn # -4 +Stack_FPReturn # -4 + +; the code and private workspace area + AREA OverLayMgrArea, PIC, CODE , READONLY + +STRLR STR lr, [pc, #-8] ; a word that is to be matched in PCITs + +; Store 2 words which are the addresses of the start and end of the workspace +WorkSpace DCD |Overlay$$Data$$Base| +WorkSpaceEnd DCD |Overlay$$Data$$Limit| +InitFlag DCD InitDoneFlag + +|Image$$overlay_init| ROUT +; Initialise overlay manager. +; In the AIF format this is is called from offset 8 in header. This routine has +; to pass control to the zero initialisation code. +; In Non AIF formats this routine has to be called explicitly e.g. from +; a customised rtstand.s . +; +; In the AIF example the entire root segment is copied to the load address. +; +; In the non AIF example only the RW part of the root is copied. +; + LDR ip,WorkSpace + IF :DEF:AIF_EXAMPLE + STR lr,[ip,#Work_LRSave] + + ADD ip,ip,#Work_RSave + STMIA ip,{r0-r3} + +; +; Look at the AIF header and add compute the total size of the AIF header +; + SUB r1,lr,#0xC + + LDR r0,[r1,#0x28] + + LDR r2,[r1,#0x14] + LDR r3,[r1,#0x18] + ADD r2,r2,r3 + LDR r3,[r1,#0x1C] + ADD r2,r2,r3 + +; +; A system specific Memory Copy call. r0 is the destination area. +; r1 is the source area. +; r2 is the block size in bytes. +; + BL MemCopy + LDR ip,WorkSpace + LDR lr,[ip,#Work_LRSave] + ADD ip,ip,#Work_RSave + SUB lr,lr,#12 + LDR lr,[lr,#0x28] + ADD lr,lr,#12 + LDMIA ip,{r0-r3} +; +; Return to the Zero Initialisation Code in the AIF header. +; + ADD pc,lr,#ZeroInitCodeOffset-12 + ELSE + LDR ip,WorkSpace + ADD ip,ip,#Work_RSave + STMIA ip,{r0-r2,lr} + + LDR r0,=|Image$$RW$$Base| + LDR r1,=|Image$$RO$$Limit| + LDR r2,=|Image$$ZI$$Limit| + SUB r2,r2,r1 + BL MemCopy + + LDR ip,WorkSpace + ADD ip,ip,#Work_RSave + LDMIA ip,{r0-r2,PC} + ENDIF + + DCD 0 ; Not needed for a real system but needed when using ARMSD + ; is used to simulate a ROM based system. +; entry point + +|Image$$load_seg| ROUT +; +; called when segment has been called but is not loaded +; presume ip is corruptible by this + LDR ip, WorkSpace + ADD ip, ip, #Work_RSave + STMIA ip, {r0-r8} ; save working registers + MRS r4, CPSR ; Save status register -it'll get stored in the + ; workspace later. +; (save in my workspace because stack is untouchable during procedure call) + LDR r0, InitFlag + LDRB r1, [r0] + CMP r1, #0 + BNE InitDone + +;Initialise Return Handlers on first call to this routine + MOV r1, #1 + STRB r1, [r0] ; set InitDone flag + LDR r0, WorkSpace +; r0 points to workspace +; corrupts r0-r3,lr +; create and initialise return handler linked list + MOV r2, #0 + STR r2, [r0, #Work_HStack] ; initialise start of handler list with NULL + ADD r1, r0, #Work_ReturnHandlersArea ; Start of heap space + STR r1, [r0, #Work_HFree] ; Start of list of free handlers point to heap space + LDR r0, WorkSpaceEnd ; for test in loop to make sure.. + SUBS r0, r0, #RHandl_Size ; ..I dont overrun in init +01 ADD r3, r1, #RHandl_Size ; next handler +; set up link to point to next handler (in fact consecutive locations) + STR r3, [r1, #RHandl_Link] + MOV r1, r3 ; next handler + CMP r1, r0 ; test for end of workspace + BLT %BT01 + SUB r1, r1, #RHandl_Size ; previous handler + STR r2, [r1, #RHandl_Link] ; NULL-terminate list + +InitDone + LDR r3, WorkSpace + STR r4, [r3, #Work_PSRSave] ; CPSR read into R4 before the InitDone + ; test. + MOV r8,lr ; + LDR r0, [r8, #-8] ; saved r14... (is end of PCIT) + STR r0, [r3, #Work_LRSave] ; ...save it here ready for retry + LDR r0, STRLR ; look for this... + SUB r1, r8, #8 ; ... starting at last overwrite +01 LDR r2, [r1, #-4]! + CMP r2, r0 ; must stop on guard word... + BNE %B01 + ADD r1, r1, #4 ; gone one too far... + STR r1, [r3, #Work_PCSave] ; where to resume at + +load_segment + +; ip -> the register save area; r8 -> the PCIT section of the segment to load. +; First re-initialise the PCIT section (if any) which clashes with this one... + + ADD r1, r8, #PCITSect_Clashes + LDR r0, [r8, #PCITSect_ClashSz] +01 SUBS r0, r0, #4 + BLT Done_Reinit ; nothing left to do + LDR r7, [r1], #4 ; a clashing segment... + LDRB r2, [r7, #PCITSect_Flags] ; its flags (0 if unloaded) + CMPS r2, #0 ; is it loaded? + BEQ %B01 ; no, so look again + +; clashing segment is loaded (clearly, there can only be 1 such segment) +; mark it as unloaded and reinitialise its PCIT +; r7 -> PCITSection of clashing loaded segment + + MOV r0, #0 + STRB r0, [r7, #PCITSect_Flags] ; mark as unloaded + LDR r0, [r7, #PCITSect_Vecsize] + SUB r1, r7, #4 ; end of vector + LDR r2, STRLR ; init value to store in the vector... +02 STR r2, [r1, #-4]! ;> + SUBS r0, r0, #4 ;> loop to initialise the PCIT segment + BGT %B02 ;> +; Now we check the chain of call frames on the stack for return addresses + +; which have been invalidated by loading this segment and install handlers +; for each invalidated return. +; Note: r8 identifies the segment being loaded; r7 the segment being unloaded. + + BL check_for_invalidated_returns +Done_Reinit + +; All segment clashes have now been dealt with, as have the re-setting +; of the segment-loaded flags and the intercepting of invalidated returns. +; So, now load the required segment. + +Retry +; +; Call a routine to load the overlay segment. +; First parameter is the length of the segment name. +; The second parameter is the address of the segment name +; The third parameter is the base address of the segement. +; The routine returns the segment length in r0. +; + MOV r0,#12 + ADD r1, r8, #PCITSect_Name + LDR r2, [ r8, #PCITSect_Base] + BL LoadOverlaySegment + + TEQ r0,#0 + MOVEQ r0,#2 + BEQ SevereErrorHandler + + LDR ip,WorkSpace + ADD ip,ip,#Work_RSave +; +; Mark the segment as loaded. +; + MOV r1,#1 + STRB r1, [r8, #PCITSect_Flags] + + LDR r2, [r8, #PCITSect_Base] + ADD r0, r2, r0 ; start + length = end of file + +; The segment's entry vector is at the end of the segment... +; ...copy it to the PCIT section identified by r8. + + LDR r1, [r8, #PCITSect_Vecsize] + SUB r3, r8, #8 ; end of entry vector... + MOV r4, #0 ; for data initialisation +01 LDR r2, [r0, #-4]! ;>loop to copy + STR r4, [r0] ; (zero-init possible data section) + STR r2, [r3], #-4 ;>the segment's PCIT + SUBS r1, r1, #4 ;>section into the + BGT %B01 ;>global PCIT + +; Finally, continue, unabashed... + + LDR r3, WorkSpace + LDR r3, [r3,#Work_PSRSave] + MSR CPSR,r3 + + LDMIA ip, {r0-r8, lr, pc} + +load_seg_and_ret +; presume ip is corruptible by this + LDR ip, WorkSpace + ADD ip, ip, #Work_RSave + STMIA ip, {r0-r8} ; save working registers +; (save in my workspace because stack is untouchable during procedure call) + LDR r3, WorkSpace + MRS r8, CPSR + STR r8, [r3, #Work_PSRSave] + +; lr points to the return handler + MOV r8, lr + ; load return handler fields RealLR, Segment, Link + LDMIA r8, {r0, r1, r2} + SUB r8, r8, #4 ; point to true start of return handler before BL + STR r0, [r3, #Work_LRSave] + STR r0, [r3, #Work_PCSave] +; Now unchain the handler and return it to the free pool +; HStack points to this handler + LDR r0, [r3, #Work_HStack] + CMPS r0, r8 + MOVNE r0, #1 + BNE SevereErrorHandler + STR r2, [r3, #Work_HStack] ; new top of handler stack + LDR r2, [r3, #Work_HFree] + STR r2, [r8, #RHandl_Link] ; Link -> old HFree + STR r8, [r3, #Work_HFree] ; new free list + MOV r8, r1 ; segment to load + B load_segment + +check_for_invalidated_returns +; Note: r8 identifies the segment being loaded; r7 the segment being unloaded. +; Note: check for returns invalidated by a call NOT for returns invalidated by +; a return! In the 2nd case, the saved LR and saved PC are identical. + LDR r5, WorkSpace + ADD r6, r5, #Work_LRSave ; 1st location to check + LDMIA r6, {r0, r1} ; saved LR & PC + CMPS r0, r1 + MOVEQ pc, lr ; identical => returning... + MOV r0, fp ; temporary FP... +01 LDR r1, [r6] ; the saved return address... + LDR r2, [r5, #Work_HStack] ; top of handler stack + CMPS r1, r2 ; found the most recent handler, so + MOVEQ pc, lr ; abort the search + LDR r2, [r7, #PCITSect_Base] + CMPS r1, r2 ; see if >= base... + BLT %F02 + LDR r2, [r7, #PCITSect_Limit] + CMPS r1, r2 ; ...and < limit ? + BLT FoundClash +02 CMPS r0, #0 ; bottom of stack? + MOVEQ pc, lr ; yes => return + ADD r6, r0, #Stack_LRReturn + LDR r0, [r0, #Stack_FPReturn] ; previous FP + B %B01 +FoundClash + LDR r0, [r5, #Work_HFree] ; head of chain of free handlers + CMPS r0, #0 + MOVEQ r0, #2 + BEQ SevereErrorHandler +; Transfer the next free handler to head of the handler stack. + LDR r1, [r0, #RHandl_Link] ; next free handler + STR r1, [r5, #Work_HFree] + LDR r1, [r5, #Work_HStack] ; the active handler stack + STR r1, [r0, #RHandl_Link] + STR r0, [r5, #Work_HStack] ; now with the latest handler linked in +; Initialise the handler with a BL load_seg_and_ret, RealLR and Segment. + ADR r1, load_seg_and_ret + SUB r1, r1, r0 ; byte offset for BL in handler + SUB r1, r1, #8 ; correct for PC off by 8 + MOV r1, r1, ASR #2 ; word offset + BIC r1, r1, #&FF000000 + ORR r1, r1, #&EB000000 ; code for BL + STR r1, [r0, #RHandl_Branch] + + LDR r1, [r6] ; LRReturn on stack + STR r1, [r0, #RHandl_RealLR] ; RealLR + STR r0, [r6] ; patch stack to return to handler + + STR r7, [r0, #RHandl_Segment] ; segment to re-load on return + MOVS pc, lr ; and return + + AREA OverlayInit, DATA +InitDoneFlag DCD 0 + + END +Appendix B +---------- +main.c +------ + +#include +#include +#define INBUFFSIZE 192 +#define OUTBUFFSIZE 257 + +static char inBuff[INBUFFSIZE]; +static char outBuff[OUTBUFFSIZE]; +static int charCount=0; + +extern int getData(char *,int); +extern int uuencode(char *, char *, int); +extern int _sys_flen(int ); +extern int _sys_open(char *,int ); +extern int _sys_read(int, void *, int, int ); +extern int _sys_close(int); + +int main(int argc,char **argv) +{ + int uuCount; + charCount = getData(inBuff,sizeof(inBuff)); + if (charCount<0) { + fprintf(stderr,"Error reading data.\n"); + } + else { + uuCount=uuencode(inBuff,outBuff,charCount); + outBuff[uuCount]='\0'; + puts(outBuff); + } + return 0; +} + +void MemCopy(void *d,void *s,int c) +{ + memmove(d,s,c); +} + +int LoadOverlaySegment(int nameLen,char *name,void *baseAdr) +{ + char name0[16]; + int length; + int fh; + + memmove(name0,name,nameLen); + name0[nameLen]='\0'; +#define OPEN_B 1 +#define OPEN_R 0 + + fh = _sys_open(name0,OPEN_B|OPEN_R); + if (fh==0) return 0; + length = _sys_flen(fh); + (void)_sys_read(fh,baseAdr,length,0); + (void)_sys_close(fh); + return length; +} + +getdata.c +--------- +#include + +int getData(char *buffer,int length) +{ + int charsIn; + int charRead; + charsIn=0; + for (charsIn=0;charsIn>2); + t1=in[1]; + out[1]=' '+((t0<<4)&0x30)+(t1>>4); + t2=in[2]; + out[2]=' '+((t1<<2)&0x3C)+ (t2>>6); + out[3]=' '+(t2&0x3F); + } + return result; +} + +maininit.s +---------- + AREA MainWithOverlayInit, CODE, READONLY + IMPORT |Image$$overlay_init| + IMPORT __main + + ENTRY + BL |Image$$overlay_init| + BL __main + END + + +Makefile +-------- + +LIB= + +.c.o: + armcc -bi -c -APCS 3/32/noswst $< + +.s.o: + armasm -bi -APCS 3/32/noswst $< + +all: ov/root + +ov/root: main.o uue.o getdata.o overmgr.o maininit.o startup.o + armlink -bin -base 0x40000 -data 0x10000 -ov ovlist \ + -o ov maininit.o startup.o main.o overmgr.o uue.o getdata.o \ + -FIRST maininit.o ${LIB}/armlib.32b -map -symbols - -list tS.map \ + -v + +startup.o: startup.s + +overmgr.o: overmgr.s + +maininit.o: maininit.s + +main.o: main.c + +uue.o: uue.c + +getdata.o: getdata.c + diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/OVERLAY/UUE.C b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/OVERLAY/UUE.C new file mode 100644 index 0000000..fa06e2e --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/OVERLAY/UUE.C @@ -0,0 +1,23 @@ +/* + A simple routine to UUENCODE a buffer. It does not split up the + uuencoded data into lines and append encode count bytes though. + It assumes that the input buffer is an integer multiple of 3 bytes long. + The number of bytes written to the output buffer is returned. +*/ +unsigned int uuencode(unsigned char *in,unsigned char *out,unsigned int count) +{ + unsigned char t0; + unsigned char t1; + unsigned char t2; + unsigned int result=0; + for (;count;count-=3,in+=3,out+=4,result+=4) { + t0=in[0]; + *out=' '+(t0>>2); + t1=in[1]; + out[1]=' '+((t0<<4)&0x30)+(t1>>4); + t2=in[2]; + out[2]=' '+((t1<<2)&0x3C)+ (t2>>6); + out[3]=' '+(t2&0x3F); + } + return result; +} diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/PROGC/DSPDIV.C b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/PROGC/DSPDIV.C new file mode 100644 index 0000000..c805d33 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/PROGC/DSPDIV.C @@ -0,0 +1,18 @@ +#include +#include + +int main(int argc, char *argv[]) +{ + if (argc != 3) + puts("needs 2 numeric args"); + else + { + __sdiv32by16 result; + + result = __rt_sdiv32by16(atoi(argv[1]), atoi(argv[2])); + + printf("quotient %d\n", result.quot); + printf("remainder %d\n", result.rem); + } + return 0; +} diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/REENT/CONFIG.H b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/REENT/CONFIG.H new file mode 100644 index 0000000..18f6fbf --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/REENT/CONFIG.H @@ -0,0 +1,74 @@ +/* + * config.h - modified specially for reentrant strlib. + * Copyright (C) Advanced RISC Machines Limited 1994. All rights reserved. + */ + +#define BYTESEX_EVEN 1 /* little-endian */ +/*#define BYTESEX_ODD 1 -- BIG-endian */ + +/* + * Define this to get a shared library with an initialised data image in the + * library. Undefine it to get the data image in the library stub. Remember + * To modify strshl in step (the line containing + {}). + */ +#define DATA_IN_LIBRARY 1 /* needs +{} in strshl */ + +#include "interns.h" + +#define memcpy_c +#define memmove_c +#define memchr_c +#define memcmp_c +#define memset_c +#define strcat_c +#define strchr_c +#define strcmp_c +#define strcoll_c +#define strcpy_c +#define strcspn_c +#define strerror_c +#define strlen_c +#define strncat_c +#define strncmp_c +#define strncpy_c +#define strpbrk_c +#define strrchr_c +#define strspn_c +#define strstr_c +#ifndef DATA_IN_LIBRARY +#define strtok_c +#endif +#define strxfrm_c +#define _strerror_c + +#include + +static char *_hostos_error_string(unsigned int n, char *v) +{ char *s = v; + int j; + strcpy(s, "unknown shared string-library error 0x"); + s += strlen(s); + for (j = 0; j < 8; ++ j) + { *s++ = "0123456789ABCDEF"[n >> 28]; + n <<= 4; + } + *s = 0; + return v; +} + + +#ifdef DATA_IN_LIBRARY + +static char *saves1 = NULL; + +char *strtok(char *s1, const char *s2) +{ char *s0; + if (s1 == 0) s1 = (saves1 == NULL) ? "" : saves1; /* use saved pointer */ + if (*(s1 += strspn(s1,s2)) == 0) s0 = 0; /* no tokens */ + else { s0 = s1; + if (*(s1 += strcspn(s1,s2)) != 0) *s1++ = 0; /* insert 0 if nec */ + } + return (saves1 = s1, s0); +} + +#endif diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/REENT/DYNLINK.S b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/REENT/DYNLINK.S new file mode 100644 index 0000000..571740a --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/REENT/DYNLINK.S @@ -0,0 +1,72 @@ + AREA |DynamicLinker|, CODE, READONLY, REENTRANT + + EXPORT |__rt_dynlink| + +|__rt_dynlink| +; Enter from a call through the stub vector with r0-r6, lr saved on sp... +; ip (the 'new sb' value) is the index of the proxy function in the stub +; vector which caused this entry to the dynamic linker and identifies +; which call to resume after linking. +; On entry r0 points to the 4-word dynamic linker entry veneer at the +; end of the stub vector. + + MOV r6, r0 + LDR r5, [r6, #-8] ; # entries - 1 + ADD r5, r5, #1 ; # entries + MOV r4, ip ; resume index + +; r6+24 points to the EFT parameter block; call the library location function +; to return a pointer to the matching library... Here we assume it's loaded +; at 0x40000... + +; In the following line, the Makefile relies on a space after '#' and on the +; contents of the comment. DO NOT CHANGE THESE OR Makefile WILL FAIL. + + MOV r0, # 0x40000 ; EFT Address (DO NOT ALTER THIS COMMENT) + +; r0 now points to the EFT + LDR ip, [r0] ; #entries + CMPS ip, r5 + BLT Botched ; not enough entries to init the stub + + LDR ip, [r6, #16] ; stub data len + BIC ip, ip, #3 ; word aligned, I insist... + ADD r3, r0, #4 + LDR r3, [r3, r5, LSL #2] ; library data len... + CMPS r3, ip + BNE Botched + + LDR r3, [r6, #20] ; stub data dest + SUB r2, r0, ip ; library data src - precedes EFT +01 SUBS ip, ip, #4 ; word by word copy loop + LDRGE r1, [r2], #4 + STRGE r1, [r3], #4 + BGE %B01 + + LDR ip, [r6, #12] ; length of the inter-LU data area + ADD r3, r6, #24 ; end of the inter-LU data area... + SUB r3, r3, ip ; sb = start of inter-LU data area + + LDR r2, [r6, #-8]! ; index of stub entry +00 SUB ip, r5, #1 ; index of the lib entry + CMPS ip, r2 ; is this lib entry in the stub? + SUBGT r5, r5, #1 ; no, skip it + BGT %B00 + CMPS r2, r4 ; found the retry index? + MOVEQ lr, r6 ; yes: remember it + LDR ip, [r0, r5, lsl #2] ; entry point offset + ADD ip, ip, r0 ; entry point address + STMIA r6, {r3, ip} ; save {sb, pc} + LDR r2, [r6, #-8]! ; load index and decrement r6... + TST r2, #&ff000000 ; ... or if loaded instruction? + LDRNE r2, [r6, #-8]! ; load index and decrement r6 if instr + SUBS r5, r5, #1 + BGT %B00 + + MOV ip, lr ; retry address + LDMFD sp!, {r0-r6, lr} ; restore saved regs + LDMIA ip, {ip, pc} ; and retry the call + +Botched B Botched + + END diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/REENT/INTERNS.H b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/REENT/INTERNS.H new file mode 100644 index 0000000..3a3fd1a --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/REENT/INTERNS.H @@ -0,0 +1,12 @@ +/* + * Dummy interns.h sufficient to compile strlib. + * Copyright (C) Advanced RISC Machines Limited 1994. All rights reserved. + */ + +#ifndef __internals_h +#define __internals_h + +extern char *_strerror(int n, char *v); +extern void __set_strcoll_table(const unsigned char *table); + +#endif diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/REENT/MAIN.S b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/REENT/MAIN.S new file mode 100644 index 0000000..552f24d --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/REENT/MAIN.S @@ -0,0 +1,26 @@ + EXPORT __main + IMPORT main + IMPORT |sb$$interLUdata$$Base| + +SWI_GetEnv * &10 +SWI_Exit * &11 + + AREA |StartupCode|, CODE, READONLY, REENTRANT + +; +; This is the initial entry point to the image. +; (The compiler ensures it is linked in to the image by generating a reference +; to __main from the object module generated from compiling a file containing +; an extern main()). + ENTRY + +; We have to establish a stack for C, initialise the library, then call _main +; (which will set up the arguments for main, then call it). +|__main| + LDR r9, =|sb$$interLUdata$$Base| + SWI SWI_GetEnv ; to decide heap limit + MOV r13, r1 ; top of program workspace + BL |main| + SWI SWI_Exit + + END diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/REENT/MAKEFILE b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/REENT/MAKEFILE new file mode 100644 index 0000000..e51ed42 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/REENT/MAKEFILE @@ -0,0 +1,101 @@ +# Copyright (C) Advanced RISC Machines Limited 1994. All rights reserved. +# Makefile for shared string library (reentrant APCS) example. + +CLIBSRC=../../cl +CC=armcc +LD=armlink +AS=armasm +SD=armsd + +# If you change -li below and in the $(SD) command later, you MUST change +# config.h to #define BYTESEX_ODD, not BYTESEX_EVEN. This Makefile and all +# the sources it uses assume little-endian operation. + +RCFLAGS=-li -apcs 3/32bit/reent -zps1 +RAFLAGS=-li -apcs 3/32bit/reent + +.SILENT: + +all: + echo "Use 'make run' to run the test" + echo "Use 'make build' to build the test" + echo "Use 'make clean' to tidy up afterwards" + +# A armsd.ini file is used to load the shared string library so that its +# EFT starts at 0x4000 (built in to dynlink.s - see below). You can alter +# this provided you do so carefully... + +build: rstub.o strtest armsd.ini + echo "Now use 'make run' to run the test" + +run: strlib strtest armsd.ini + $(SD) -li strtest + echo "Now use 'make clean' to tidy up" + +clean: + rm -f armsd.ini map maplib strtest strlib *.o + +# Here we make a sharable library out of the ANSI C Library's string functions. +# We make a reentrant stub for use with a reentrant client. + +rstub.o: string.o + echo Making strlib and rstub.o + echo "Please ignore (Warning) Attribute conflict" + echo "" + $(LD) -o rstub.o -reent -s - -shl strshl -map string.o > maplib + @echo Made strlib and a matching reentrant stub + +# The armsd.ini file instructs armsd to load the shared string library so its +# EFT is located at the address assumed by dynlink.s. Here, we grep the +# assumed address from dynlink.s and the EFT's offset from the library's +# map file (maplib). We load the library at
-. +# eg. +# armsd: getfile strlib 0x40000-0x0009c8 +# ^^^^^^^^ value of EFT$$Offset from maplib +# armsd: go + +armsd.ini: dynlink.s maplib + echo Making $@ + fgrep 'EFT Address' dynlink.s | \ + awk '{printf "getfile strlib %s",$$4}' - > armsd.ini + fgrep 'EFT$$$$Offset' maplib | awk '{printf "-0x%s\n",$$2}' - >> armsd.ini + +# We use a local dummy copy of interns.h and a local copy of config.h which +# patches around some deficiencies in the library sources prior to r1.6.2. + +string.o: $(CLIBSRC)/string.c interns.h config.h + echo Making $@ + $(CC) $(RCFLAGS) -c -I. $(CLIBSRC)/string.c + +# Here we link the test program with: +# - the dynamic linker (dynlink.o) +# - the reentrant stub of the library +# - a small piece of startup code which provides the same run-line +# environment as a fully reentrant, shared C library kernel would provide. + +strtest: strtest.o dynlink.o main.o + echo Making $@ + echo "Please ignore (Waring) Attribute conflict" + echo "" + $(LD) -d -o strtest strtest.o dynlink.o rstub.o main.o -map > map + +strtest.o: strtest.c + echo Making $@ + $(CC) $(RCFLAGS) -c strtest.c + +dynlink.o: dynlink.s + echo Making $@ + $(AS) $(RAFLAGS) dynlink.s dynlink.o + +main.o: main.s + echo Making $@ + $(AS) $(RAFLAGS) main.s main.o + +# Null dependencies + +maplib: rstub.o + +strlib: rstub.o + +dynlink.s: + diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/REENT/STRSHL b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/REENT/STRSHL new file mode 100644 index 0000000..3eee490 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/REENT/STRSHL @@ -0,0 +1,34 @@ +> strlib \ + 0x40000 + +; Include an image of the initialised data in the library itself. +; Dynlink will copy this at run time to a zero-initialised area +; reserved by the stub. + ++() + +; Functions exported from the sharable string library + +memcpy +memmove +memchr +memcmp +strcat +strchr +strcmp +strcoll +__set_strcoll_table +strcpy +strcspn +strerror +_strerror +strlen +strncat +strncmp +strncpy +strpbrk +strrchr +strspn +strstr +strtok +strxfrm diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/REENT/STRSTUB.APJ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/REENT/STRSTUB.APJ new file mode 100644 index 0000000..95d64b1 Binary files /dev/null and b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/REENT/STRSTUB.APJ differ diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/REENT/STRTEST.APJ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/REENT/STRTEST.APJ new file mode 100644 index 0000000..93109e2 Binary files /dev/null and b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/REENT/STRTEST.APJ differ diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/REENT/STRTEST.C b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/REENT/STRTEST.C new file mode 100644 index 0000000..a2ee0a3 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/REENT/STRTEST.C @@ -0,0 +1,18 @@ +extern char *strerror(int); + +__swi(0) void writec(int); + + +static void puts(char *s) +{ int ch; + for (ch = *s; ch != 0; ch = *++s) writec(ch); +} + +int main() +{ + puts("\nstrerror(42) returns \""); + puts(strerror(42)); + puts("\"\n\r\n"); + + return 0; +} diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/ROM/EX.C b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/ROM/EX.C new file mode 100644 index 0000000..4430177 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/ROM/EX.C @@ -0,0 +1,52 @@ +/* We use the following Debug Monitor SWIs to write things out + * in this example + */ +extern __swi(0) WriteC(char c); /* Write a character */ +extern __swi(2) Write0(char *s); /* Write a string */ + +/* The following symbols are defined by the linker and define + * various memory regions which may need to be copied or initialised + */ +extern char Image$$RO$$Limit[]; +extern char Image$$RW$$Base[]; + + +/* We define some more meaningfull names here */ +#define rom_data_base Image$$RO$$Limit +#define ram_data_base Image$$RW$$Base + +/* This is an example of a pre-initialised variable. */ +static unsigned factory_id = 0xAA55AA55; /* Factory set ID */ + +/* This is an example of an uninitialised (or 0 initialised) variable */ +static char display[8][40]; /* Screen buffer */ + +static const char hex[16] = "0123456789ABCDEF"; + +static void pr_hex(unsigned n) +{ + int i; + + for (i = 0; i < 8; i++) { + WriteC(hex[n >> 28]); + n <<= 4; + } +} + +void C_Entry(void) +{ + if (rom_data_base == ram_data_base) { + Write0("Warning: Image has been linked as an application. To link as a ROM image\r\n"); + Write0(" link with the options -RO -RW \r\n"); + } + + Write0("'factory_id' is at address "); + pr_hex((unsigned)&factory_id); + Write0(", contents = "); + pr_hex((unsigned)factory_id); + Write0("\r\n"); + + Write0("'display' is at address "); + pr_hex((unsigned)display); + Write0("\r\n"); +} diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/ROM/INIT.S b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/ROM/INIT.S new file mode 100644 index 0000000..3786ac7 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/ROM/INIT.S @@ -0,0 +1,164 @@ +; +; The AREA must have the attribute READONLY, otherwise the linker will not +; place it in ROM. +; +; The AREA must have the attribute CODE, otherwise the assembler will not +; let us put any code in this AREA +; +; Note the '|' character is used to surround any symbols which contain +; non standard characters like '!'. + + AREA Init, CODE, READONLY + +; Now some standard definitions... + +Mode_IRQ EQU 0x12 +Mode_SVC EQU 0x13 + +I_Bit EQU 0x80 +F_Bit EQU 0x40 + +SWI_Exit EQU 0x11 + +; Locations of various things in our memory system + +RAM_Base EQU 0x10000000 ; 64k RAM at this base +RAM_Limit EQU 0x10010000 + +IRQ_Stack EQU RAM_Limit ; 1K IRQ stack at top of memory +SVC_Stack EQU RAM_Limit-1024 ; followed by SVC stack + +; --- Define __main & set entry point + ENTRY + +; --- Setup interrupt / exception vectors + IF :DEF: ROM_AT_ADDRESS_ZERO +; If the ROM is at address 0 this is just a sequence of branches + B Reset_Handler + B Undefined_Handler + B SWI_Handler + B Prefetch_Handler + B Abort_Handler + NOP ; Reserved vector + B IRQ_Handler + B FIQ_Handler + ELSE +; Otherwise we copy a sequence of LDR PC instructions over the vectors +; (Note: We copy LDR PC instructions because branch instructions +; could not simply be copied, the offset in the branch instruction +; would have to be modified so that it branched into ROM. Also, a +; branch instructions might not reach if the ROM is at an address +; > 32M). + MOV R8, #0 + ADR R9, Vector_Init_Block + LDMIA R9!, {R0-R7} + STMIA R8!, {R0-R7} + LDMIA R9!, {R0-R7} + STMIA R8!, {R0-R7} + +; Now fall into the LDR PC, Reset_Addr instruction which will continue +; execution at 'Reset_Handler' + +Vector_Init_Block + LDR PC, Reset_Addr + LDR PC, Undefined_Addr + LDR PC, SWI_Addr + LDR PC, Prefetch_Addr + LDR PC, Abort_Addr + NOP + LDR PC, IRQ_Addr + LDR PC, FIQ_Addr + +Reset_Addr DCD Reset_Handler +Undefined_Addr DCD Undefined_Handler +SWI_Addr DCD SWI_Handler +Prefetch_Addr DCD Prefetch_Handler +Abort_Addr DCD Abort_Handler + DCD 0 ; Reserved vector +IRQ_Addr DCD IRQ_Handler +FIQ_Addr DCD FIQ_Handler + ENDIF + +; The following handlers do not do anything useful in this example. +; +Undefined_Handler + B Undefined_Handler +SWI_Handler + B SWI_Handler +Prefetch_Handler + B Prefetch_Handler +Abort_Handler + B Abort_Handler +IRQ_Handler + B IRQ_Handler +FIQ_Handler + B FIQ_Handler + +; The RESET entry point +Reset_Handler + +; --- Initialise stack pointer registers +; Enter IRQ mode and set up the IRQ stack pointer + MOV R0, #Mode_IRQ:OR:I_Bit:OR:F_Bit ; No interrupts + MSR CPSR, R0 + LDR R13, =IRQ_Stack + +; Set up other stack pointers if necessary + ; ... + +; Set up the SVC stack pointer last and return to SVC mode + MOV R0, #Mode_SVC:OR:I_Bit:OR:F_Bit ; No interrupts + MSR CPSR, R0 + LDR R13, =SVC_Stack + +; --- Initialise memory system + ; ... + +; --- Initialise critical IO devices + ; ... + +; --- Initialise interrupt system variables here + ; ... + +; --- Enable interrupts +; Now safe to enable interrupts, so do this and remain in SVC mode + MOV R0, #Mode_SVC:OR:F_Bit ; Only IRQ enabled + MSR CPSR, R0 + +; --- Initialise memory required by C code + + IMPORT |Image$$RO$$Limit| ; End of ROM code (=start of ROM data) + IMPORT |Image$$RW$$Base| ; Base of RAM to initialise + IMPORT |Image$$ZI$$Base| ; Base and limit of area + IMPORT |Image$$ZI$$Limit| ; to zero initialise + + LDR r0, =|Image$$RO$$Limit| ; Get pointer to ROM data + LDR r1, =|Image$$RW$$Base| ; and RAM copy + LDR r3, =|Image$$ZI$$Base| ; Zero init base => top of initialised data + CMP r0, r1 ; Check that they are different + BEQ %1 +0 CMP r1, r3 ; Copy init data + LDRCC r2, [r0], #4 + STRCC r2, [r1], #4 + BCC %0 +1 LDR r1, =|Image$$ZI$$Limit| ; Top of zero init segment + MOV r2, #0 +2 CMP r3, r1 ; Zero init + STRCC r2, [r3], #4 + BCC %2 + +; --- Now we enter the C code + + IMPORT C_Entry + [ :DEF:THUMB + ORR lr, pc, #1 + BX lr + CODE16 ; Next instruction will be Thumb + ] + BL C_Entry +; In a real application we wouldn't normally expect to return, however +; this example does so the debug monitor swi SWI_Exit is used to halt the +; application. + SWI SWI_Exit + + END diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/ROM/SPRINTF.C b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/ROM/SPRINTF.C new file mode 100644 index 0000000..6a5d4c9 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/ROM/SPRINTF.C @@ -0,0 +1,31 @@ +#include + +/* We use the following Debug Monitor SWIs to write things out + * in this example + */ +extern __swi(2) Write0(char *s); /* Write a string */ + +/* The following symbols are defined by the linker and define + * various memory regions which may need to be copied or initialised + */ +extern char Image$$RO$$Base[]; +extern char Image$$RO$$Limit[]; +extern char Image$$RW$$Base[]; + +/* We define some more meaningful names here */ +#define rom_code_base Image$$RO$$Base +#define rom_data_base Image$$RO$$Limit +#define ram_data_base Image$$RW$$Base + +void C_Entry(void) +{ + char s[80]; + + if (rom_data_base == ram_data_base) { + Write0("Warning: Image has been linked as an application. To link as a ROM image\r\n"); + Write0(" link with the options -RO -RW \r\n"); + } + + sprintf(s, "ROM is at address %p, RAM is at address %p\n", rom_code_base, ram_data_base); + Write0(s); +} diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/ARMSD.OB b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/ARMSD.OB new file mode 100644 index 0000000..c15049e --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/ARMSD.OB @@ -0,0 +1,3 @@ +get app/root 0x80000 +get app/copydata 0x84800 +let pc=0x80000 diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/GETDATA.C b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/GETDATA.C new file mode 100644 index 0000000..20f3c90 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/GETDATA.C @@ -0,0 +1,16 @@ +#include + +int getData(char *buffer,int length) +{ + int charsIn; + int charRead; + charsIn=0; + for (charsIn=0;charsIn +#include +#define INBUFFSIZE 192 +#define OUTBUFFSIZE 257 + +static char IDstring[]="This is initailised data."; +static char inBuff[INBUFFSIZE]; +static char outBuff[OUTBUFFSIZE]; +static int charCount=0; + +extern int getData(char *,int); +extern int uuencode(char *, char *, int); + +int main(int argc,char **argv) +{ + int uuCount; + charCount = getData(inBuff,sizeof(inBuff)); + if (charCount<0) { + fprintf(stderr,"Error reading data.\n"); + } + else { + uuCount=uuencode(inBuff,outBuff,charCount); + outBuff[uuCount]='\0'; + puts(outBuff); + } + return 0; +} + +void MemCopy(void *d,void *s,int c) +{ + memmove(d,s,c); +} + diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/MAININIT.S b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/MAININIT.S new file mode 100644 index 0000000..3fed52a --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/MAININIT.S @@ -0,0 +1,12 @@ + AREA MainWithOverlayInit, CODE, READONLY + IMPORT |Image$$overlay_init| + IMPORT InitialiseApp + IMPORT __entry + EXPORT __main + + ENTRY +__main + BL InitialiseApp + BL |Image$$overlay_init| + BL __entry + END diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/MAKEFILE b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/MAKEFILE new file mode 100644 index 0000000..6dadf7a --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/MAKEFILE @@ -0,0 +1,29 @@ +CC=/xdevt/rel200/gccsunos/armcc -bi -c +LD= /xdevt/rel200/gccsunos/armlink +LIB=/xdevt/rel200/lib/armlib.32b + +.c.o: + $(CC) -APCS 3/32/noswst $< + +all: app/root + +app/root: main.o uue.o getdata.o overmgrs.o initapp.o maininit.o + $(LD) -bin -scatter scatdes -o app maininit.o main.o overmgrs.o uue.o \ + getdata.o initapp.o $(LIB) -map -symbols - -first maininit.o \ + -list tS.map -v + +maininit.o: maininit.s + armasm -bi -APCS 3/32/noswst maininit.s + +initapp.o: initapp.s + armasm -bi -APCS 3/32/noswst initapp.s + +overmgrs.o: overmgrs.s + armasm -bi -APCS 3/32/noswst overmgrs.s + +main.o: main.c + +uue.o: uue.c + +getdata.o: getdata.c + diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/OVERMGRS.S b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/OVERMGRS.S new file mode 100644 index 0000000..c9504a0 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/OVERMGRS.S @@ -0,0 +1,326 @@ + +;;; Copyright (C) Advanced RISC Machines Ltd., 1991 +;; +;; For use with a scatter loaded application with embedded overlays. + + EXPORT |Image$$overlay_init| + EXPORT |Image$$load_seg| + +; pointers to start and end of workspace area supplied by the linker + IMPORT |Overlay$$Data$$Base| + IMPORT |Overlay$$Data$$Limit| + IMPORT |Root$$OverlayTable| + IMPORT MemCopy + IMPORT SevereErrorHandler, WEAK + +ZeroInitCodeOffset EQU 64 + +; Layout of workspace allocated by the linker pointed to by Overlay$$Data +; This area is automatically zero-initialised AFTER overlay_init is called +; offsets are prefixed with Work_ + ^ 0 +Work_HStack # 4 ; top of stack of allocated handlers +Work_HFree # 4 ; head of free-list +Work_RSave # 9*4 ; for R0-R8 +Work_LRSave # 4 ; saved lr +Work_PCSave # 4 ; saved PC +Work_PSRSave # 4 ; saved CPSR +Work_ReturnHandlersArea EQU @ ; rest of this memory is treated as heap + ; space for the return handlers +Work_MinSize EQU @ + 32 * RHandl_Size + +; Return handler. 1 is allocated per inter-segment procedure call +; allocated and free lists of handlers are pointed to from HStack and HFree +; offsets are prefixed with RHandl_ + ^ 0 +RHandl_Branch # 4 ; BL load_seg_and_ret +RHandl_RealLR # 4 ; space for the real return address +RHandl_Segment # 4 ; -> PCIT section of segment to load +RHandl_Link # 4 ; -> next in stack order +RHandl_Size EQU @ + +; set up by check_for_invalidated_returns. + +; PCITSection. 1 per segment stored in root segment, allocated by linker +; offsets are prefixed with PCITSect_ + ^ 0 +PCITSect_Vecsize # 4 ; .-4-EntryV ; size of entry vector +PCITSect_Base # 4 ; used by load_segment; not initialised +PCITSect_Limit # 4 ; used by load_segment; not initialised +PCITSect_Name # 11 ; <11 bytes> ; 10-char segment name + NUL in 11 bytes +PCITSect_Flags # 1 ; ...and a flag byte +PCITSect_ClashSz # 4 ; PCITEnd-.-4 ; size of table following +PCITSect_Clashes # 4 ; >table of pointers to clashing segments + +; Stack structure (all offsets are negative) +; defined in procedure call standard +; offsets are prefixed with Stack_ + ^ 0 +Stack_SaveMask # -4 +Stack_LRReturn # -4 +Stack_SPReturn # -4 +Stack_FPReturn # -4 + +; the code and private workspace area + AREA OverLayMgrArea, PIC, CODE , READONLY + +STRLR STR lr, [pc, #-8] ; a word that is to be matched in PCITs + +; Store 2 words which are the addresses of the start and end of the workspace +WorkSpace DCD |Overlay$$Data$$Base| +WorkSpaceEnd DCD |Overlay$$Data$$Limit| +InitFlag DCD InitDoneFlag + +|Image$$overlay_init| ROUT +; Initialise overlay manager. +; In the AIF format this is is called from offset 8 in header. This routine has +; to pass control to the zero initialisation code. +; In Non AIF formats this routine has to be called explicitly e.g. from +; a customised rtstand.s . +; +; In the AIF example the entire root segment is copied to the load address. +; +; In the non AIF example only the RW part of the root is copied. +; + MOV pc,lr + + DCD 0 ; Not needed for a real system but needed when using ARMSD + ; is used to simulate a ROM based system. +; entry point + +|Image$$load_seg| ROUT +; +; called when segment has been called but is not loaded +; presume ip is corruptible by this + LDR ip, WorkSpace + ADD ip, ip, #Work_RSave + STMIA ip, {r0-r8} ; save working registers + MRS r4, CPSR ; Save status register -it'll get stored in the + ; workspace later. +; (save in my workspace because stack is untouchable during procedure call) + LDR r0, InitFlag + LDRB r1, [r0] + CMP r1, #0 + BNE InitDone + +;Initialise Return Handlers on first call to this routine + MOV r1, #1 + STRB r1, [r0] ; set InitDone flag + LDR r0, WorkSpace +; r0 points to workspace +; corrupts r0-r3,lr +; create and initialise return handler linked list + MOV r2, #0 + STR r2, [r0, #Work_HStack] ; initialise start of handler list with NULL + ADD r1, r0, #Work_ReturnHandlersArea ; Start of heap space + STR r1, [r0, #Work_HFree] ; Start of list of free handlers point to heap space + LDR r0, WorkSpaceEnd ; for test in loop to make sure.. + SUBS r0, r0, #RHandl_Size ; ..I dont overrun in init +01 ADD r3, r1, #RHandl_Size ; next handler +; set up link to point to next handler (in fact consecutive locations) + STR r3, [r1, #RHandl_Link] + MOV r1, r3 ; next handler + CMP r1, r0 ; test for end of workspace + BLT %BT01 + SUB r1, r1, #RHandl_Size ; previous handler + STR r2, [r1, #RHandl_Link] ; NULL-terminate list + +InitDone + LDR r3, WorkSpace + STR r4, [r3, #Work_PSRSave] ; CPSR read into R4 before the InitDone + ; test. + MOV r8,lr ; + LDR r0, [r8, #-8] ; saved r14... (is end of PCIT) + STR r0, [r3, #Work_LRSave] ; ...save it here ready for retry + LDR r0, STRLR ; look for this... + SUB r1, r8, #8 ; ... starting at last overwrite +01 LDR r2, [r1, #-4]! + CMP r2, r0 ; must stop on guard word... + BNE %B01 + ADD r1, r1, #4 ; gone one too far... + STR r1, [r3, #Work_PCSave] ; where to resume at + +load_segment + +; ip -> the register save area; r8 -> the PCIT section of the segment to load. +; First re-initialise the PCIT section (if any) which clashes with this one... + + ADD r1, r8, #PCITSect_Clashes + LDR r0, [r8, #PCITSect_ClashSz] +01 SUBS r0, r0, #4 + BLT Done_Reinit ; nothing left to do + LDR r7, [r1], #4 ; a clashing segment... + LDRB r2, [r7, #PCITSect_Flags] ; its flags (0 if unloaded) + CMPS r2, #0 ; is it loaded? + BEQ %B01 ; no, so look again + +; clashing segment is loaded (clearly, there can only be 1 such segment) +; mark it as unloaded and reinitialise its PCIT +; r7 -> PCITSection of clashing loaded segment + + MOV r0, #0 + STRB r0, [r7, #PCITSect_Flags] ; mark as unloaded + LDR r0, [r7, #PCITSect_Vecsize] + SUB r1, r7, #4 ; end of vector + LDR r2, STRLR ; init value to store in the vector... +02 STR r2, [r1, #-4]! ;> + SUBS r0, r0, #4 ;> loop to initialise the PCIT segment + BGT %B02 ;> +; Now we check the chain of call frames on the stack for return addresses + +; which have been invalidated by loading this segment and install handlers +; for each invalidated return. +; Note: r8 identifies the segment being loaded; r7 the segment being unloaded. + + BL check_for_invalidated_returns +Done_Reinit + +; All segment clashes have now been dealt with, as have the re-setting +; of the segment-loaded flags and the intercepting of invalidated returns. +; So, now load the required segment. + +Retry +; +; Use the overlay table generated by the linker. The table format is as follows: +; The first word in the table is contains the number of entries in the table. +; The follows that number of table entries. Each entry is 3 words long: +; Word 1 Length of the segment in bytes. +; Word 2 Execution address of the PCIT section address. This is compared +; against the value in R8. If the values are equal we have found +; the entry for the called overlay. +; Word 3 Load address of the segment. +; Segment names are not used. +; + LDR r0,=|Root$$OverlayTable| + LDR r1,[r0],#4 +search_loop + CMP r1,#0 + MOVEQ r0,#2 ; The end the table has been reached and the + BEQ SevereErrorHandler ; segemnt has not been found. + LDMIA r0!,{r2,r3,r4} + CMP r8,r3 + SUBNE r1,r1,#1 + BNE search_loop + + LDR r0,[ r8, #PCITSect_Base ] + MOV r1,r4 + MOV r4,r2 + BL MemCopy + + LDR ip,WorkSpace + ADD ip,ip,#Work_RSave +; +; Mark the segment as loaded. +; + MOV r1,#1 + STRB r1, [r8, #PCITSect_Flags] + + LDR r0,[ r8, #PCITSect_Base ] + ADD r0,r0,r4 + +; The segment's entry vector is at the end of the segment... +; ...copy it to the PCIT section identified by r8. + + LDR r1, [r8, #PCITSect_Vecsize] + SUB r3, r8, #8 ; end of entry vector... + MOV r4, #0 ; for data initialisation +01 LDR r2, [r0, #-4]! ;>loop to copy + STR r4, [r0] ; (zero-init possible data section) + STR r2, [r3], #-4 ;>the segment's PCIT + SUBS r1, r1, #4 ;>section into the + BGT %B01 ;>global PCIT + +; Finally, continue, unabashed... + + LDR r3, WorkSpace + LDR r3, [r3,#Work_PSRSave] + MSR CPSR,r3 + + LDMIA ip, {r0-r8, lr, pc} + +load_seg_and_ret +; presume ip is corruptible by this + LDR ip, WorkSpace + ADD ip, ip, #Work_RSave + STMIA ip, {r0-r8} ; save working registers +; (save in my workspace because stack is untouchable during procedure call) + LDR r3, WorkSpace + MRS r8, CPSR + STR r8, [r3, #Work_PSRSave] + +; lr points to the return handler + MOV r8, lr + ; load return handler fields RealLR, Segment, Link + LDMIA r8, {r0, r1, r2} + SUB r8, r8, #4 ; point to true start of return handler before BL + STR r0, [r3, #Work_LRSave] + STR r0, [r3, #Work_PCSave] +; Now unchain the handler and return it to the free pool +; HStack points to this handler + LDR r0, [r3, #Work_HStack] + CMPS r0, r8 + MOVNE r0, #1 + BNE SevereErrorHandler + STR r2, [r3, #Work_HStack] ; new top of handler stack + LDR r2, [r3, #Work_HFree] + STR r2, [r8, #RHandl_Link] ; Link -> old HFree + STR r8, [r3, #Work_HFree] ; new free list + MOV r8, r1 ; segment to load + B load_segment + +check_for_invalidated_returns +; Note: r8 identifies the segment being loaded; r7 the segment being unloaded. +; Note: check for returns invalidated by a call NOT for returns invalidated by +; a return! In the 2nd case, the saved LR and saved PC are identical. + LDR r5, WorkSpace + ADD r6, r5, #Work_LRSave ; 1st location to check + LDMIA r6, {r0, r1} ; saved LR & PC + CMPS r0, r1 + MOVEQ pc, lr ; identical => returning... + MOV r0, fp ; temporary FP... +01 LDR r1, [r6] ; the saved return address... + LDR r2, [r5, #Work_HStack] ; top of handler stack + CMPS r1, r2 ; found the most recent handler, so + MOVEQ pc, lr ; abort the search + LDR r2, [r7, #PCITSect_Base] + CMPS r1, r2 ; see if >= base... + BLT %F02 + LDR r2, [r7, #PCITSect_Limit] + CMPS r1, r2 ; ...and < limit ? + BLT FoundClash +02 CMPS r0, #0 ; bottom of stack? + MOVEQ pc, lr ; yes => return + ADD r6, r0, #Stack_LRReturn + LDR r0, [r0, #Stack_FPReturn] ; previous FP + B %B01 +FoundClash + LDR r0, [r5, #Work_HFree] ; head of chain of free handlers + CMPS r0, #0 + MOVEQ r0, #2 + BEQ SevereErrorHandler +; Transfer the next free handler to head of the handler stack. + LDR r1, [r0, #RHandl_Link] ; next free handler + STR r1, [r5, #Work_HFree] + LDR r1, [r5, #Work_HStack] ; the active handler stack + STR r1, [r0, #RHandl_Link] + STR r0, [r5, #Work_HStack] ; now with the latest handler linked in +; Initialise the handler with a BL load_seg_and_ret, RealLR and Segment. + ADR r1, load_seg_and_ret + SUB r1, r1, r0 ; byte offset for BL in handler + SUB r1, r1, #8 ; correct for PC off by 8 + MOV r1, r1, ASR #2 ; word offset + BIC r1, r1, #&FF000000 + ORR r1, r1, #&EB000000 ; code for BL + STR r1, [r0, #RHandl_Branch] + + LDR r1, [r6] ; LRReturn on stack + STR r1, [r0, #RHandl_RealLR] ; RealLR + STR r0, [r6] ; patch stack to return to handler + + STR r7, [r0, #RHandl_Segment] ; segment to re-load on return + MOV pc, lr ; and return + + AREA OverlayInit, DATA +InitDoneFlag DCD 0 + + END diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/README.TXT b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/README.TXT new file mode 100644 index 0000000..5748912 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/README.TXT @@ -0,0 +1,745 @@ + Use Of The Linker For Scatter Loading + ------------------------------------- + +Version 0.1 Apr 1995 Laurence Bond +Version 1.0 May 1995 Laurence Bond + +Introduction +------------ + +This application note describes an example which uses uses the linker to produce +a scatter loaded application with overlays. The linker section in the Software +Development Toolkit manual should read in conjunction with this note. Other +information can be found in the Programming Techinques manual. + +The example will work only with Tools 200 Beta or later. + +Example Memory Structure +------------------------ +In this example the memory is assumed to have the following structure + + 0x00000 - 0x3FFFF - Unused + 0x40000 - 0x43FFF - SRAM + 0x44000 - 0x7FFFF - Unused + 0x80000 - 0x9FFFF - ROM + +Overlays will be placed in ROM and copied into the SRAM when needed. Also the +overlay manager and all read/write initialised data will be copied into the +SRAM. + +Overlay Manager +--------------- +The linker does not provide the overlay manager. The overlay manager is user +supplied code which controls the overlay mechanism. The linker produces the +appropriate binary files and constructs the PCITs (Procedure Call Indirection +Tables). +The overlay manager must define two publicly visible symbols +Image$$overlay_init and Image$$load_seg. + +Image$$overlay_init is used to initialise the overlay manager. +Image$$overlay_init does not get called automatically. However it should be +called just after the application has been entered. This is the case in this +example although the routine just returns to the caller. The initialisation +of the overlay manager workspace would done as part of the initialisation +of the scatter loaded image. + +Image$$load_seg is the procedure that performs the functions of the overlay +manager described in the Software Development toolkit manual. + +The overlay manager listed in Appendix A works with 32 bit processor modes only. +It is operating system independent. The code area is read-only. The flag +used to indicate whether the overlay manager has initialised its workspace is +in a read-write area of its own. The code to load a segment uses the linker +generated table that relates PCIT section addresses to the location of the +overlay segments in their load regions. The address of this table is bound to +the linker generated symbol Root$$OverlayTable. + +To aid operating system independence, two routines are be called by the +overlay manager. These should could have replaced by inline code. However to aid +clarity, this has not been done. The routines are: + + MemCopy + r0 - Destination address + r1 - Source Address + r2 - Block length in bytes + + This routine does not return anything. + + SevereErrorHandler + r0 - A value indicating which error condition has occurred. + + This symbol is a weak reference and need not be resolved. In the example + no such routine is provided. However in a real application one should be + provided. + + +A Pitfall In Using The C library +-------------------------------- +In this example, a the C library was found to interfere with loaded segments. +The reason is that in the default C library, the heap is initialised to start +at the address Image$$RW$$Limit. + +For example, the segments could get corrupted by use of the memory +allocation package if they are located to an address greater that this. A malloc +could grab some memory from the heap which just happened to be part of an +overlayed segments code. Similarly loading an overlay segment could result in +the segment data being loaded into an area used by the heap, thereby corrupting +the heap. In this application the default libraray is used. The data allcoated +on the heap is sufficently smaller that it fits between the end of the root +read/write execution region and the start of the root read only execution +region. If one were to examine the memory immediately above the address +Image$$RW$$Limit one will find the data buffers used by the standard input and +output channels. + + +The Example Application +----------------------- +The example application reads a sequence of characters, terminated either by +end of file or a newline, from stdin. These characters are then UU encoded and +output to stdout. + +The application consists of 3 C source files and two assembler files excluding +the overlay manager. The C files are as follows: + + getdata.c + This defines a function, getData, which reads the characters into a + buffer passed to it by the main program. + + uue.c + This defines a function, uue, which takes an input buffer passed + in by the main program and writes the UU encoded equivalent into + another buffer supplied by the main program. + + main.c + This contains the C main program and example implementations of + the functions LoadOverlaySegment and MemCopy needed by the overlay + manager. Two statically allocated data buffers are also defined. + + The main program calls getData to read data into a buffer. This buffer + is then passed to uue as the input buffer. The output buffer is zero + terminated after uue returns and the results written to stdout. + + MemCopy is just a call to memmove - a standard C library function. + +Together with the overlay manager these C files could define the whole +application. However the initialisation of the image is not done by any code in +these source modules. + +A new entry point is required which initialises the application and the overlay manager. This supplied by the file maininit.s . +The source code except for the overlay manager can be found in Appendix B. + +The buffers defined in main.c will be read-write data in the root read/write +execution region.The assembler entry point code, the functions defined in +main.c and any C library functions extracted from the library will be in the +root read only execution region. The overlay manager and its initialised data +will be moved to address 0x40000. + +The function uue will be in an overlay segment named seg_1. The function getData +will be in an overlay segment named seg_2. + +Testing The Application +----------------------- +The application was built big endian and linked with the following linker +options: + armlink -bin -scatter scatdes -o app maininit.o main.o overmgrs.o \ + uue.o getdata.o initapp.o armlib.32b -map -symbols - \ + -first maininit.o -list tS.map -v + +This command produces the subdirectory app which will contain 2 pure binary +files - one per load region. + +The full Makefile and the scatter load description file (scatdes) can be found +in Appendix B. + +The application is then loaded into ARMSD. As it is not an AIF file, the +loading process is done manually. + + armsd -bi + armsd: get app/root 0x80000 + armsd: get app/copydata 0x84800 + armsd: let pc=0x80000 + +The entry point is at 0x80000 by virtue of the -FIRST option on the linker and +the code structure in maininit.s + + armsd: go + Hello World (The user types Hello World) + 2&5L;&\@5V]R;&0* (The program prints this.) + +This is correct when compared against UUENCODE on SunOS 4.1.3. Note that +initial encoded count byte is not output. + + Program terminated normally at PC = 0x00040248 + 0x00040248: 0xef000011 .... : swi 0x11 + armsd: q + Quitting + +Appendix A +---------- + + +;;; Copyright (C) Advanced RISC Machines Ltd., 1991 +;; +;; For use with a scatter loaded application with embedded overlays. + + EXPORT |Image$$overlay_init| + EXPORT |Image$$load_seg| + +; pointers to start and end of workspace area supplied by the linker + IMPORT |Overlay$$Data$$Base| + IMPORT |Overlay$$Data$$Limit| + IMPORT |Root$$OverlayTable| + IMPORT MemCopy + IMPORT SevereErrorHandler, WEAK + +ZeroInitCodeOffset EQU 64 + +; Layout of workspace allocated by the linker pointed to by Overlay$$Data +; This area is automatically zero-initialised AFTER overlay_init is called +; offsets are prefixed with Work_ + ^ 0 +Work_HStack # 4 ; top of stack of allocated handlers +Work_HFree # 4 ; head of free-list +Work_RSave # 9*4 ; for R0-R8 +Work_LRSave # 4 ; saved lr +Work_PCSave # 4 ; saved PC +Work_PSRSave # 4 ; saved CPSR +Work_ReturnHandlersArea EQU @ ; rest of this memory is treated as heap + ; space for the return handlers +Work_MinSize EQU @ + 32 * RHandl_Size + +; Return handler. 1 is allocated per inter-segment procedure call +; allocated and free lists of handlers are pointed to from HStack and HFree +; offsets are prefixed with RHandl_ + ^ 0 +RHandl_Branch # 4 ; BL load_seg_and_ret +RHandl_RealLR # 4 ; space for the real return address +RHandl_Segment # 4 ; -> PCIT section of segment to load +RHandl_Link # 4 ; -> next in stack order +RHandl_Size EQU @ + +; set up by check_for_invalidated_returns. + +; PCITSection. 1 per segment stored in root segment, allocated by linker +; offsets are prefixed with PCITSect_ + ^ 0 +PCITSect_Vecsize # 4 ; .-4-EntryV ; size of entry vector +PCITSect_Base # 4 ; used by load_segment; not initialised +PCITSect_Limit # 4 ; used by load_segment; not initialised +PCITSect_Name # 11 ; <11 bytes> ; 10-char segment name + NUL in 11 bytes +PCITSect_Flags # 1 ; ...and a flag byte +PCITSect_ClashSz # 4 ; PCITEnd-.-4 ; size of table following +PCITSect_Clashes # 4 ; >table of pointers to clashing segments + +; Stack structure (all offsets are negative) +; defined in procedure call standard +; offsets are prefixed with Stack_ + ^ 0 +Stack_SaveMask # -4 +Stack_LRReturn # -4 +Stack_SPReturn # -4 +Stack_FPReturn # -4 + +; the code and private workspace area + AREA OverLayMgrArea, PIC, CODE , READONLY + +STRLR STR lr, [pc, #-8] ; a word that is to be matched in PCITs + +; Store 2 words which are the addresses of the start and end of the workspace +WorkSpace DCD |Overlay$$Data$$Base| +WorkSpaceEnd DCD |Overlay$$Data$$Limit| +InitFlag DCD InitDoneFlag + +|Image$$overlay_init| ROUT +; Initialise overlay manager. +; In the AIF format this is is called from offset 8 in header. This routine has +; to pass control to the zero initialisation code. +; In Non AIF formats this routine has to be called explicitly e.g. from +; a customised rtstand.s . +; +; In the AIF example the entire root segment is copied to the load address. +; +; In the non AIF example only the RW part of the root is copied. +; + MOV pc,lr + + DCD 0 ; Not needed for a real system but needed when using ARMSD + ; is used to simulate a ROM based system. +; entry point + +|Image$$load_seg| ROUT +; +; called when segment has been called but is not loaded +; presume ip is corruptible by this + LDR ip, WorkSpace + ADD ip, ip, #Work_RSave + STMIA ip, {r0-r8} ; save working registers + MRS r4, CPSR ; Save status register -it'll get stored in the + ; workspace later. +; (save in my workspace because stack is untouchable during procedure call) + LDR r0, InitFlag + LDRB r1, [r0] + CMP r1, #0 + BNE InitDone + +;Initialise Return Handlers on first call to this routine + MOV r1, #1 + STRB r1, [r0] ; set InitDone flag + LDR r0, WorkSpace +; r0 points to workspace +; corrupts r0-r3,lr +; create and initialise return handler linked list + MOV r2, #0 + STR r2, [r0, #Work_HStack] ; initialise start of handler list with NULL + ADD r1, r0, #Work_ReturnHandlersArea ; Start of heap space + STR r1, [r0, #Work_HFree] ; Start of list of free handlers point to heap space + LDR r0, WorkSpaceEnd ; for test in loop to make sure.. + SUBS r0, r0, #RHandl_Size ; ..I dont overrun in init +01 ADD r3, r1, #RHandl_Size ; next handler +; set up link to point to next handler (in fact consecutive locations) + STR r3, [r1, #RHandl_Link] + MOV r1, r3 ; next handler + CMP r1, r0 ; test for end of workspace + BLT %BT01 + SUB r1, r1, #RHandl_Size ; previous handler + STR r2, [r1, #RHandl_Link] ; NULL-terminate list + +InitDone + LDR r3, WorkSpace + STR r4, [r3, #Work_PSRSave] ; CPSR read into R4 before the InitDone + ; test. + MOV r8,lr ; + LDR r0, [r8, #-8] ; saved r14... (is end of PCIT) + STR r0, [r3, #Work_LRSave] ; ...save it here ready for retry + LDR r0, STRLR ; look for this... + SUB r1, r8, #8 ; ... starting at last overwrite +01 LDR r2, [r1, #-4]! + CMP r2, r0 ; must stop on guard word... + BNE %B01 + ADD r1, r1, #4 ; gone one too far... + STR r1, [r3, #Work_PCSave] ; where to resume at + +load_segment + +; ip -> the register save area; r8 -> the PCIT section of the segment to load. +; First re-initialise the PCIT section (if any) which clashes with this one... + + ADD r1, r8, #PCITSect_Clashes + LDR r0, [r8, #PCITSect_ClashSz] +01 SUBS r0, r0, #4 + BLT Done_Reinit ; nothing left to do + LDR r7, [r1], #4 ; a clashing segment... + LDRB r2, [r7, #PCITSect_Flags] ; its flags (0 if unloaded) + CMPS r2, #0 ; is it loaded? + BEQ %B01 ; no, so look again + +; clashing segment is loaded (clearly, there can only be 1 such segment) +; mark it as unloaded and reinitialise its PCIT +; r7 -> PCITSection of clashing loaded segment + + MOV r0, #0 + STRB r0, [r7, #PCITSect_Flags] ; mark as unloaded + LDR r0, [r7, #PCITSect_Vecsize] + SUB r1, r7, #4 ; end of vector + LDR r2, STRLR ; init value to store in the vector... +02 STR r2, [r1, #-4]! ;> + SUBS r0, r0, #4 ;> loop to initialise the PCIT segment + BGT %B02 ;> +; Now we check the chain of call frames on the stack for return addresses + +; which have been invalidated by loading this segment and install handlers +; for each invalidated return. +; Note: r8 identifies the segment being loaded; r7 the segment being unloaded. + + BL check_for_invalidated_returns +Done_Reinit + +; All segment clashes have now been dealt with, as have the re-setting +; of the segment-loaded flags and the intercepting of invalidated returns. +; So, now load the required segment. + +Retry +; +; Use the overlay table generated by the linker. The table format is as follows: +; The first word in the table is contains the number of entries in the table. +; The follows that number of table entries. Each entry is 3 words long: +; Word 1 Length of the segment in bytes. +; Word 2 Execution address of the PCIT section address. This is compared +; against the value in R8. If the values are equal we have found +; the entry for the called overlay. +; Word 3 Load address of the segment. +; Segment names are not used. +; + LDR r0,=|Root$$OverlayTable| + LDR r1,[r0],#4 +search_loop + CMP r1,#0 + MOVEQ r0,#2 ; The end the table has been reached and the + BEQ SevereErrorHandler ; segemnt has not been found. + LDMIA r0!,{r2,r3,r4} + CMP r8,r3 + SUBNE r1,r1,#1 + BNE search_loop + + LDR r0,[ r8, #PCITSect_Base ] + MOV r1,r4 + MOV r4,r2 + BL MemCopy + + LDR ip,WorkSpace + ADD ip,ip,#Work_RSave +; +; Mark the segment as loaded. +; + MOV r1,#1 + STRB r1, [r8, #PCITSect_Flags] + + LDR r0,[ r8, #PCITSect_Base ] + ADD r0,r0,r4 + +; The segment's entry vector is at the end of the segment... +; ...copy it to the PCIT section identified by r8. + + LDR r1, [r8, #PCITSect_Vecsize] + SUB r3, r8, #8 ; end of entry vector... + MOV r4, #0 ; for data initialisation +01 LDR r2, [r0, #-4]! ;>loop to copy + STR r4, [r0] ; (zero-init possible data section) + STR r2, [r3], #-4 ;>the segment's PCIT + SUBS r1, r1, #4 ;>section into the + BGT %B01 ;>global PCIT + +; Finally, continue, unabashed... + + LDR r3, WorkSpace + LDR r3, [r3,#Work_PSRSave] + MSR CPSR,r3 + + LDMIA ip, {r0-r8, lr, pc} + +load_seg_and_ret +; presume ip is corruptible by this + LDR ip, WorkSpace + ADD ip, ip, #Work_RSave + STMIA ip, {r0-r8} ; save working registers +; (save in my workspace because stack is untouchable during procedure call) + LDR r3, WorkSpace + MRS r8, CPSR + STR r8, [r3, #Work_PSRSave] + +; lr points to the return handler + MOV r8, lr + ; load return handler fields RealLR, Segment, Link + LDMIA r8, {r0, r1, r2} + SUB r8, r8, #4 ; point to true start of return handler before BL + STR r0, [r3, #Work_LRSave] + STR r0, [r3, #Work_PCSave] +; Now unchain the handler and return it to the free pool +; HStack points to this handler + LDR r0, [r3, #Work_HStack] + CMPS r0, r8 + MOVNE r0, #1 + BNE SevereErrorHandler + STR r2, [r3, #Work_HStack] ; new top of handler stack + LDR r2, [r3, #Work_HFree] + STR r2, [r8, #RHandl_Link] ; Link -> old HFree + STR r8, [r3, #Work_HFree] ; new free list + MOV r8, r1 ; segment to load + B load_segment + +check_for_invalidated_returns +; Note: r8 identifies the segment being loaded; r7 the segment being unloaded. +; Note: check for returns invalidated by a call NOT for returns invalidated by +; a return! In the 2nd case, the saved LR and saved PC are identical. + LDR r5, WorkSpace + ADD r6, r5, #Work_LRSave ; 1st location to check + LDMIA r6, {r0, r1} ; saved LR & PC + CMPS r0, r1 + MOVEQ pc, lr ; identical => returning... + MOV r0, fp ; temporary FP... +01 LDR r1, [r6] ; the saved return address... + LDR r2, [r5, #Work_HStack] ; top of handler stack + CMPS r1, r2 ; found the most recent handler, so + MOVEQ pc, lr ; abort the search + LDR r2, [r7, #PCITSect_Base] + CMPS r1, r2 ; see if >= base... + BLT %F02 + LDR r2, [r7, #PCITSect_Limit] + CMPS r1, r2 ; ...and < limit ? + BLT FoundClash +02 CMPS r0, #0 ; bottom of stack? + MOVEQ pc, lr ; yes => return + ADD r6, r0, #Stack_LRReturn + LDR r0, [r0, #Stack_FPReturn] ; previous FP + B %B01 +FoundClash + LDR r0, [r5, #Work_HFree] ; head of chain of free handlers + CMPS r0, #0 + MOVEQ r0, #2 + BEQ SevereErrorHandler +; Transfer the next free handler to head of the handler stack. + LDR r1, [r0, #RHandl_Link] ; next free handler + STR r1, [r5, #Work_HFree] + LDR r1, [r5, #Work_HStack] ; the active handler stack + STR r1, [r0, #RHandl_Link] + STR r0, [r5, #Work_HStack] ; now with the latest handler linked in +; Initialise the handler with a BL load_seg_and_ret, RealLR and Segment. + ADR r1, load_seg_and_ret + SUB r1, r1, r0 ; byte offset for BL in handler + SUB r1, r1, #8 ; correct for PC off by 8 + MOV r1, r1, ASR #2 ; word offset + BIC r1, r1, #&FF000000 + ORR r1, r1, #&EB000000 ; code for BL + STR r1, [r0, #RHandl_Branch] + + LDR r1, [r6] ; LRReturn on stack + STR r1, [r0, #RHandl_RealLR] ; RealLR + STR r0, [r6] ; patch stack to return to handler + + STR r7, [r0, #RHandl_Segment] ; segment to re-load on return + MOV pc, lr ; and return + + AREA OverlayInit, DATA +InitDoneFlag DCD 0 + + END +Appendix B +---------- +main.c +------ + +#include +#include +#define INBUFFSIZE 192 +#define OUTBUFFSIZE 257 + +/* + This is used to check whether the initialised data has been copied + correctly. +*/ +static char IDstring[]="This is initialised data."; +static char inBuff[INBUFFSIZE]; +static char outBuff[OUTBUFFSIZE]; +static int charCount=0; + +extern int getData(char *,int); +extern int uuencode(char *, char *, int); + +int main(int argc,char **argv) +{ + int uuCount; + charCount = getData(inBuff,sizeof(inBuff)); + if (charCount<0) { + fprintf(stderr,"Error reading data.\n"); + } + else { + uuCount=uuencode(inBuff,outBuff,charCount); + outBuff[uuCount]='\0'; + puts(outBuff); + } + return 0; +} + +void MemCopy(void *d,void *s,int c) +{ + memmove(d,s,c); +} + +getdata.c +--------- + +int getData(char *buffer,int length) +{ + int charsIn; + int charRead; + charsIn=0; + for (charsIn=0;charsIn>2); + t1=in[1]; + out[1]=' '+((t0<<4)&0x30)+(t1>>4); + t2=in[2]; + out[2]=' '+((t1<<2)&0x3C)+ (t2>>6); + out[3]=' '+(t2&0x3F); + } + encodedCount += count; + return result; +} + +maininit.s +---------- + + AREA MainWithOverlayInit, CODE, READONLY + IMPORT |Image$$overlay_init| + IMPORT InitialiseApp + IMPORT __entry + EXPORT __main + + ENTRY +__main + BL InitialiseApp + BL |Image$$overlay_init| + BL __entry + END + +Makefile +-------- + +LIB= + +.c.o: + armcc -c -bi -APCS 3/32/noswst $< + +.s.o: + armasm -bi -APCS 3/32/noswst $< + +all: app/root + +app/root: main.o uue.o getdata.o overmgrs.o initapp.o maininit.o + armlink -bin -scatter scatdes -o app maininit.o main.o overmgrs.o \ + uue.o getdata.o initapp.o $(LIB)/armlib.32b -map -symbols - \ + -first maininit.o -list tS.map -NOUNUSED -v > tS.log + +maininit.o: maininit.s + +initapp.o: initapp.s + +overmgrs.o: overmgrs.s + +main.o: main.c + +uue.o: uue.c + +getdata.o: getdata.c + +scatdes +------- + +; +; Position the root load region at 0x80000. Limit the size so it does not +; overlap the overlay segments in the ROM load region. +; +ROOT 0x80000 0x4800 +; +; Position the root read/write execution region . +; +ROOT-DATA 0x43000 + +copydata 0x84800 { + seg_1 0x42000 OVERLAY { uue.o } + seg_2 0x42000 OVERLAY { getdata.o } + overmgr 0x40000 { overmgrs.o(+RO, +RW) } ; Position the overlay manager + ; code and data in the SRAM +} + +initapp.s +--------- + + AREA InitApp, CODE , READONLY + EXPORT InitialiseApp +InitialiseApp + ADR r0,ziTable + MOV R3,#0 +ziLoop + LDR r1,[r0],#4 + CMP r1,#0 + BEQ initLoop + LDR r2,[r0],#4 +ziFillLoop + STR r3,[r2],#4 + SUBS r1,r1,#4 + BNE ziFillLoop + B ziLoop + +initLoop + LDR r1,[r0],#4 + CMP r1,#0 + MOVEQ pc,lr + LDMIA r0!,{r2,r3} + CMP r1,#16 + BLT copyWords +copy4Words + LDMIA r3!,{r4,r5,r6,r7} + STMIA r2!,{r4,r5,r6,r7} + SUBS r1,r1,#16 + BGT copy4Words + BEQ initLoop +copyWords + SUBS r1,r1,#8 + LDMIAGE r3!,{r4,r5} + STMIAGE r2!,{r4,r5} + BEQ initLoop + + LDR r4,[r3] + STR r4,[r2] + + B initLoop + + MACRO + ZIEntry $execname + LCLS lensym + LCLS basesym + LCLS namecp +namecp SETS "$execname" +lensym SETS "|Image$$":CC:namecp:CC:"$$ZI$$Length|" +basesym SETS "|Image$$":CC:namecp:CC:"$$ZI$$Base|" + IMPORT $lensym + IMPORT $basesym + DCD $lensym + DCD $basesym + MEND + + MACRO + InitEntry $execname + LCLS lensym + LCLS basesym + LCLS loadsym + LCLS namecp +namecp SETS "$execname" +lensym SETS "|Image$$":CC:namecp:CC:"$$Length|" +basesym SETS "|Image$$":CC:namecp:CC:"$$Base|" +loadsym SETS "|Load$$":CC:namecp:CC:"$$Base|" + IMPORT $lensym + IMPORT $basesym + IMPORT $loadsym + DCD $lensym + DCD $basesym + DCD $loadsym + MEND + +ziTable + ZIEntry root + DCD 0 + +InitTable + InitEntry root + InitEntry overmgr + DCD 0 + END diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/SCATDES b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/SCATDES new file mode 100644 index 0000000..6ec377f --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/SCATDES @@ -0,0 +1,26 @@ +; +; +; The memory map or the system is +; +; 0x00000 - 0x3FFFF - DRAM +; 0x40000 - 0x43FFF - SRAM +; 0x44000 - 0x7FFFF - Unused +; 0x80000 - 0x9FFFF - ROM +; +; Position the root load region at 0x40000. Limit the size so it does not +; overlap the overlay segments in the ROM load region. +; +ROOT 0x80000 0x8000 +; +; Position the root read/write execution region . +; +ROOT-DATA 0x43000 + +copydata 0x88000 { + seg_1 0x42000 OVERLAY { uue.o } + seg_2 0x42000 OVERLAY { getdata.o } + overmgr 0x40000 { overmgrs.o(+RO, +RW) } ; Position the overlay manager + ; code and data in the fast SRAM +} + + diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/SCATTER.APJ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/SCATTER.APJ new file mode 100644 index 0000000..1d8d656 Binary files /dev/null and b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/SCATTER.APJ differ diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/STARTUP.S b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/STARTUP.S new file mode 100644 index 0000000..b61472a --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/STARTUP.S @@ -0,0 +1,52 @@ + AREA |!!!|, CODE, READONLY + + IMPORT __entry ; The C library entry point + + EXPORT __main + + IMPORT |Image$$RO$$Base| + IMPORT |Image$$RO$$Limit| + IMPORT |Image$$RW$$Base| + IMPORT |Image$$RW$$Limit| + IMPORT |Image$$ZI$$Base| + IMPORT |Image$$ZI$$Limit| + +;----------------------------------------------------------------------------; +; The above symbols are created by the linker to define various sections in ; +; the ROM/RAM image. ; +; ; +; Image$$RO$$Base defines the code (ROM) base address ; +; Image$$RO$$Limit defines the code limit and the start of a section of ; +; data initialisation values which are copied to RAM ; +; in __main below before main is called. ; +; Image$$RW$$Base defines the data (RAM) base address ; +; Image$$RW$$Limit defines the data end address ; +; Image$$ZI$$Base defines the base of a section to be initialised with 0s ; +; Image$$ZI$$Limit defines the end of the region to be initialised with 0s ; +; (must be the same as Image$$RW$$Limit in this model) ; +;----------------------------------------------------------------------------; + +; Code is enter in ARM mode + [ {CONFIG} = 16 + CODE32 + ] + +__main + LDR r0, =|Image$$RO$$Limit| ; Get pointer to ROM data + LDR r1, =|Image$$RW$$Base| ; and RAM copy + LDR r3, =|Image$$ZI$$Base| ; Zero init base => top of initialised data + CMP r0, r1 ; Check that they are different + BEQ %FT1 +0 CMP r1, r3 ; Copy init data + LDRCC r2, [r0], #4 + STRCC r2, [r1], #4 + BCC %BT0 +1 LDR r1, =|Image$$ZI$$Limit| ; Top of zero init segment + MOV r2, #0 +2 CMP r3, r1 ; Zero init + STRCC r2, [r3], #4 + BCC %BT2 + + B __entry + + END diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/UUE.C b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/UUE.C new file mode 100644 index 0000000..76d60c3 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SCATTER/UUE.C @@ -0,0 +1,26 @@ +/* + A simple reoutine to UUENCODE a buffer. It does not split up the + uuencoded data into lines and append encode count bytes though. + It assumes that the input buffer is an integer multiple of 3 bytes long. + The number of bytes written to the output buffer is returned. +*/ +unsigned int encodedCount=0; +unsigned int uuencode(unsigned char *in,unsigned char *out,unsigned int count) +{ + unsigned char t0; + unsigned char t1; + unsigned char t2; + unsigned int result=0; + + for (;count;count-=3,in+=3,out+=4,result+=4) { + t0=in[0]; + *out=' '+(t0>>2); + t1=in[1]; + out[1]=' '+((t0<<4)&0x30)+(t1>>4); + t2=in[2]; + out[2]=' '+((t1<<2)&0x3C)+ (t2>>6); + out[3]=' '+(t2&0x3F); + } + encodedCount += count; + return result; +} diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SORTS/ARMSD.MAP b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SORTS/ARMSD.MAP new file mode 100644 index 0000000..ba65198 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SORTS/ARMSD.MAP @@ -0,0 +1 @@ +0 80000000 RAM 4 rw 135/80 135/80 diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SORTS/SORTS.C b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SORTS/SORTS.C new file mode 100644 index 0000000..5a2afa2 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SORTS/SORTS.C @@ -0,0 +1,135 @@ +#include +#include +#include +#include + +#define N 1000 + +#if N > 1000000 +#error "Value of N too big, must be <= 1000000" +#endif + +#define LOG10_N 6 +#define N_FORMAT "%06d" + +#if N <= 1000 +static void insert_sort(char *strings[], int n) +{ + char *v, *t; + char **strp, **endp; + int i; + + endp = &strings[N-1]; + i = N-2; + do { + strp = &strings[i]; + v = strp[0]; + do { + t = strp[1]; + if (strcmp(v, t) <= 0) break; + *strp++ = t; + } while (strp < endp); + strp[0] = v; + } while (--i >= 0); +} +#endif + +static void shell_sort(char *strings[], int n) +{ + int h, i, j; + char *v; + + strings--; /* Make array 1 origin */ + h = 1; + do {h = h * 3 + 1;} while (h <= n); + do { + h = h / 3; + for (i = h + 1; i <= n; i++) { + v = strings[i]; + j = i; + while (j > h && strcmp(strings[j-h], v) > 0) { + strings[j] = strings[j-h]; + j = j-h; + } + strings[j] = v; + } + } + while (h > 1); +} + +static void randomise(char *strings[], int n) +{ + int i; + int v; + char *t; + + /* srand(clock()); /* comment out for reproducible results */ + for (i = 0; i < N; i++) { + v = rand() % N; + t = strings[v]; + strings[v] = strings[i]; + strings[i] = t; + } +} + +static void check_order(char *sort_type, char *strings[], int n) +{ + int i; + + for (i = 0; i < n; i++) { + if (atoi(strings[i]) != i) { + fprintf(stderr, "%s sort failed - exiting\n", sort_type); + exit(1); + } + } +} + +int qs_string_compare(const void *a, const void *b) +{ + return strcmp(*(char **)a, *(char **)b); +} + +int main(void) +{ + char *strings[N], *strings_copy[N]; + char buffer[N*(LOG10_N+1)]; + char *p; + clock_t starttime, endtime; + int i; + + p = buffer; + for (i = 0; i < N; i++) { + sprintf(p, N_FORMAT, i); + strings[i] = p; + p += LOG10_N+1; + } + randomise(strings, N); + +#if N <= 1000 + /* Do insertion sort */ + memcpy(strings_copy, strings, sizeof(strings)); + starttime = clock(); + insert_sort(strings_copy, N); + endtime = clock(); + check_order("Insertion", strings_copy, N); + printf("Insertion sort took %d clock ticks\n", endtime - starttime); +#else + printf("Value of N too big to use insertion sort, must be <= 1000\n"); +#endif + + /* Do shell sort */ + memcpy(strings_copy, strings, sizeof(strings)); + starttime = clock(); + shell_sort(strings_copy, N); + endtime = clock(); + check_order("Shell", strings_copy, N); + printf("Shell sort took %d clock ticks\n", endtime - starttime); + + /* Do quick sort - use built-in C library sort */ + memcpy(strings_copy, strings, sizeof(strings)); + starttime = clock(); + qsort(strings_copy, N, sizeof(char *), qs_string_compare); + endtime = clock(); + check_order("Quick", strings_copy, N); + printf("Quick sort took %d clock ticks\n", endtime - starttime); +} diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SWI/HANDLE.S b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SWI/HANDLE.S new file mode 100644 index 0000000..6056035 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SWI/HANDLE.S @@ -0,0 +1,42 @@ + AREA TopSwiHandler, CODE ; name this block of code + + EXPORT SWIHandler + EXPORT MakeChain + IMPORT C_SWI_Handler + IMPORT Dswivec +SWIHandler + SUB r13, r13, #4 ; leave space to store spsr + STMFD r13!, {r0-r12,r14} ; store registers + MOV r1, r13 ; second parameter to C routine + ; is register values. + LDR r0,[r14,#-4] ; Calculate address of SWI instruction + ; and load it into r0 + BIC r0,r0,#0xff000000 ; mask off top 8 bits of instruction + MRS r2, spsr + STR r2,[r13,#14*4] ; store spsr on stack at original r13 + BL C_SWI_Handler ; Call C routine to handle SWI + CMP r0, #0 ; Has C routine handled SWI ? + ; 0 = no, 1 = yes + LDR r2, [r13,#14*4] ; extract spsr from stack + MSR spsr,r2 ; and restore it + LDMFD r13!, {r0-r12,lr} ; Restore original registers + ADD r13,r13,#4 + ; Now need to decide whether to return from handler or to call + ; the next handler in the chain (the debugger's). + MOVNES pc,lr ; return from handler if SWI handled + LDR pc, swichain ; else jump to address containing + ; instruction to branch to address of + ; debugger's SWI handler. + +swichain + DCD 0 + +MakeChain + LDR r0, =swichain + LDR r1, =Dswivec + LDR r2, [r1] + STR r2, [r0] + MOV pc,lr + + END ; mark end of this file + diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SWI/INSTALL.C b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SWI/INSTALL.C new file mode 100644 index 0000000..9c0fadf --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SWI/INSTALL.C @@ -0,0 +1,105 @@ +#include +#include + +extern void SWIHandler (void); +extern void MakeChain (void); + +unsigned *Dswivec = (unsigned *) 0x20; /* ie place to store old one */ + +struct four_results +{ unsigned a; + unsigned b; + unsigned c; + unsigned d; +}; + +__swi (256) void my_swi_256 (void); +__swi (257) void my_swi_257 (unsigned); +__swi (258) unsigned my_swi_258 (unsigned,unsigned,unsigned,unsigned); +__swi (259) __value_in_regs struct four_results + my_swi_259 (unsigned, unsigned, unsigned,unsigned); + +unsigned Install_Handler (unsigned routine, unsigned *vector) +/* Updates contents of 'vector' to contain branch instruction */ +/* to reach 'routine' from 'vector'. Function return value is */ /* original contents of 'vector'. */ +/* NB: 'Routine' must be within range of 32Mbytes from 'vector'.*/ +{ unsigned vec, oldvec; + vec = ((routine - (unsigned)vector - 0x8)>>2); + if (vec & 0xff000000) + { printf ("Installation of Handler failed"); + exit (0); + } + vec = 0xea000000 | vec; + oldvec = *vector; + *vector = vec; + return (oldvec); +} + +void Update_Demon_Vec (unsigned *original, unsigned *Dvec) +/* Returns updated instruction 'LDR pc, [pc,#offset]' when */ +/* moved from 'original' to 'Dvec' (ie recalculates offset). */ +/* Assumes 'Dvec' is higher in memory than 'original'. */ +{ + *Dvec = ((*Dvec &0xfff) + - ((unsigned) Dvec - (unsigned) original)) + | (*Dvec & 0xfffff000); +} + +unsigned C_SWI_Handler (unsigned number, unsigned *reg) +{ unsigned done = 1; + + /* Set up parameter storage block pointers */ + unsigned *called_256 = (unsigned *) 0x24; + unsigned *param_257 = (unsigned*) 0x28; + unsigned *param_258 = (unsigned*) 0x2c; /* + 0x30,0x34,0x38 */ + unsigned *param_259 = (unsigned*) 0x3c; /* + 0x40,0x44,0x48 */ + switch (number) + { case 256: + *called_256 = 256; /* Store a value to show that */ + break; /* SWI was handled correctly. */ + case 257: + *param_257 = reg [0]; /* Store parameter */ + break; + case 258: + *param_258++ = reg [0]; /* Store parameters */ + *param_258++ = reg [1]; + *param_258++ = reg [2]; + *param_258 = reg [3]; + /* Now calculate result */ + reg [0] += reg [1] + reg [2] + reg [3]; + break; + case 259: + *param_259++ = reg [0]; /* Store parameters */ + *param_259++ = reg [1]; + *param_259++ = reg [2]; + *param_259 = reg [3]; + reg [0] *= 2; /* Calculate results */ + reg [1] *= 3; + reg [2] *= 4; + reg [3] *= 5; + break; + default: done = 0; /* SWI not handled */ + } + return (done); +} + +int main () +{ + struct four_results r_259; /* Results from SWI 259 */ + unsigned *swivec = (unsigned *)0x8; /* Pointer to SWI vector */ + *Dswivec = Install_Handler ((unsigned)SWIHandler, swivec); + Update_Demon_Vec (swivec, Dswivec); + MakeChain (); + + printf("Hello 256\n"); + my_swi_256 (); + printf("Hello 257\n"); + my_swi_257 (257); + printf("Hello 258\n"); + printf(" Result = %u\n",my_swi_258 (1,2,3,4)); + printf ("Hello 259\n"); + r_259 = my_swi_259 (10,20,30,40); + printf (" Results are: %u %u %u %u\n",r_259.a,r_259.b,r_259.c,r_259.d); + printf("The end\n"); + return (0); +} diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SWI/INSTALLH.C b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SWI/INSTALLH.C new file mode 100644 index 0000000..0413b49 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SWI/INSTALLH.C @@ -0,0 +1,17 @@ +typedef struct SWI_InstallHandler_struct +{ unsigned exception; + unsigned workspace; + unsigned handler; +} SWI_InstallHandler_block; + + +SWI_InstallHandler_block + __value_in_regs + __swi(0x70) SWI_InstallHandler(unsigned r0, unsigned r1, unsigned r2); + +void InstallHandler(SWI_InstallHandler_block *regs_in, + SWI_InstallHandler_block *regs_out) +{ *regs_out=SWI_InstallHandler(regs_in->exception, + regs_in->workspace, + regs_in->handler); +} diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SWI/NEWLINE.C b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SWI/NEWLINE.C new file mode 100644 index 0000000..25bae33 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SWI/NEWLINE.C @@ -0,0 +1,6 @@ +void __swi(0) SWI_WriteC(int ch); + +void output_newline(void) +{ SWI_WriteC(13); + SWI_WriteC(10); +} diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SWI/READLINE.C b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SWI/READLINE.C new file mode 100644 index 0000000..2168320 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SWI/READLINE.C @@ -0,0 +1,9 @@ +char __swi(4) SWI_ReadC(void); + +void readline(char *buffer) +{ char ch; + do { + *buffer++=ch=SWI_ReadC(); + } while (ch!=13); + *buffer=0; +} diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SWI/SWI.APJ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SWI/SWI.APJ new file mode 100644 index 0000000..2bbbc96 Binary files /dev/null and b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SWI/SWI.APJ differ diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SWI/SWIMANIP.C b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SWI/SWIMANIP.C new file mode 100644 index 0000000..231c76c --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/SWI/SWIMANIP.C @@ -0,0 +1,9 @@ +unsigned __swi_indirect(0x80) + SWI_ManipulateObject(unsigned operationNumber, unsigned object, + unsigned parameter); + +unsigned DoSelectedManipulation(unsigned object, unsigned parameter, + unsigned operation) +{ + return SWI_ManipulateObject(operation, object, parameter); +} diff --git a/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/UNUSED/UNUSED.C b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/UNUSED/UNUSED.C new file mode 100644 index 0000000..8e9ec27 --- /dev/null +++ b/Bachelor/Mikroprozessorsysteme2/ARM202U/EXAMPLES/UNUSED/UNUSED.C @@ -0,0 +1,14 @@ +#include + +void unused_function(void) +{ + printf("This function used to do something useful, but is now no longer called\n"); +} + +int main(void) +{ + printf("We used to call 'unused_function' here.\n"); +#if 0 + unused_function(); +#endif +} -- cgit v1.2.3