⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 divide.s

📁 HAL硬件抽象层源码
💻 S
📖 第 1 页 / 共 2 页
字号:
; Issue: 0.02/25-Nov-91
;
; Purpose: Minimal, standalone, C-library kernel.
;
; Copyright (C) 1991 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:                                                   ;
;                                                                            ;
;  - Divide (and remainder) functions.                                       ;
;                                                                            ;
; WHAT THIS CODE DOES NOT PROVIDE                                            ;
;                                                                            ;
; Support for handling traps, faults, escapes, exceptions or interrupts.     ;
;                                                                            ;
;----------------------------------------------------------------------------;


;----------------------------------------------------------------------------;
; 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.             ;
;----------------------------------------------------------------------------;

 IF :LNOT: :DEF: USE_C_LIBRARY
        EXPORT  |__rt_udiv|
        EXPORT  |__rt_udiv10|
        EXPORT  |__rt_sdiv|
        EXPORT  |__rt_sdiv10|
        EXPORT  |__rt_divtest|
 ENDIF
        IMPORT  PutString
        IMPORT  |__rt_exit|
        IMPORT  |__err_handler|, WEAK

;----------------------------------------------------------------------------;
; If __err_handler exists, errors are passed to it; otherwise, we print a    ;
; simple diagnostic message and exit.                                        ;
;----------------------------------------------------------------------------;


        AREA    |C$$code|, CODE, READONLY  ; This module's code area.        ;

;----------------------------------------------------------------------------;
; 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

;----------------------------------------------------------------------------;
; 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
        BL      PutString             ; write preamble...
        ADD     a1, v1, #4
        BL      PutString             ; write error diagnosis
        ADR     a1, RTErrorTail
        BL      PutString             ; 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|

dividebyzero
        ADR     ip, DivideByZeroError
        B       save_regs_and_trap

stackoverflow
        ADR     ip, StackOverflowError
        B       save_regs_and_trap

DivideByZeroError
        DCD     1
        DCB     "divide by 0", 0
        ALIGN

StackOverflowError
        DCD     3
        DCB     "stack overflow", 0
        ALIGN

RTErrorHead
        DCB     10, 13, "run time error: ", 0

RTErrorTail
        DCB     10, 13, "program terminated", 10, 13, 10, 13, 0

        ALIGN


;----------------------------------------------------------------------------;
; 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/ In each of these implementations we make a careful compromise between   ;
;    fastest and smallest. In some cases (e.g. divide), further unrolling of ;
;    loops will yield a speed-up. However, this affects cache and working-   ;
;    set locality and can result in a slow-down for some applications on     ;
;    some hardware. You are advised not to unroll further before considering ;
;    carefully your application and its interaction with your hardware.      ;
;    (e.g. ARM-2 vs ARM-3, external cache vs no external cache, fraction of  ;
;     run-time spent executing divide, etc.).                                ;
;                                                                            ;
;----------------------------------------------------------------------------;


|__rt_udiv|                                                           ; udiv ;
;
; Unsigned divide of a2 by a1: returns quotient in a1, remainder in a2.
; Also destroys a3, a4 and ip

        MOVS    a3, a1
        BEQ     dividebyzero
        MOV     a4, #0
        MOV     ip, #&80000000
        CMP     a2, ip
        MOVLO   ip, a2
u_loop
        CMP     ip, a3, ASL #0
        BLS     u_shifted0mod8

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -