From cda5e33778749ea8e4a720af66b66fba7ee912ae Mon Sep 17 00:00:00 2001 From: Tat-Chee Wan (USM) Date: Tue, 14 Jun 2011 13:40:52 +0800 Subject: moved hex conversion routines to its own source file --- Debugger/debug_comm.S | 434 ------------------------------------------- Debugger/debug_hexutils.S | 457 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 457 insertions(+), 434 deletions(-) create mode 100644 Debugger/debug_hexutils.S diff --git a/Debugger/debug_comm.S b/Debugger/debug_comm.S index d96fa22..baab7b7 100644 --- a/Debugger/debug_comm.S +++ b/Debugger/debug_comm.S @@ -61,443 +61,9 @@ debug_nxtCommChannel: nxt_commcmd_header: .byte NXT_GDBMSG_TELEGRAMTYPE, 0x00, 0x00 /* padded to 3 bytes */ -hex2char_lut: - .ascii "0123456789ABCDEF" - -/* Macros - */ - - -/* _hex2char_lut - * Internal routine to intialize the LUT address pointer - */ - .macro _hex2char_lut addrptr - ldr \addrptr, =hex2char_lut - .endm - -/* _hex2char_cont - * Internal routine that assumes that the LUT has been loaded. - * This macro accepts a byte sized hex value as a parameter register(7:0) and returns the - * ASCII equivalent in in the same register(7:0) - * The second parameter is the LUT address pointer register to use (assumed to be initialized) - * WARNING: Assumes that the value in register is sanity checked before invoking macro - */ - .macro _hex2char_cont reg, addrptr - ldrb \reg, [\addrptr, \reg] - .endm - -/* _hex2char - * This macro accepts a byte sized hex value as a parameter register(7:0) and returns the - * ASCII equivalent in in the same register(7:0) - * The second parameter is the LUT address pointer register to use (register content is destroyed) - * WARNING: Assumes that the value in register is sanity checked before invoking macro - */ - .macro _hex2char reg, addrptr - _hex2char_lut \addrptr - _hex2char_cont \reg, \addrptr - .endm - -/* _char2hex - * This macro accepts an ASCII char as a parameter register(7:0) and returns the - * equivalent byte sized hex value in in the same register(7:0) - * WARNING: Assumes that the char in register is a valid hex char before invoking macro - */ - .macro _char2hex reg - cmp \reg, #'A' /* If Alpha */ - bichs \reg, \reg, #ASCII_LOWER2UPPER_MASK /* Convert to Uppercase */ - subhs \reg, \reg, #7 /* Adjustment to allow for subtraction with 0x30 */ - sub \reg, \reg, #0x30 /* get final hex value */ - .endm - - .code 32 .text .align 4 - - -/* Utility Routines - * GDB requires command parameters to be specified as Big Endian values. - * However, the read/write register command expect the register contents to be specified in target byte order. - * Hence we need both versions of multibyte conversion routines for word sized values. - */ - -/* hex2char - * This routine accepts a byte sized hex value in R0(7:0) and returns the - * ASCII equivalent in R0(7:0) - */ - .global hex2char - -hex2char: - stmfd sp!, {r1,lr} - and r0, #NIBBLE0 /* make sure that input is sane */ - _hex2char r0, r1 - ldmfd sp!, {r1,pc} - -/* char2hex - * This routine accepts an ASCII character in R0(7:0) and returns the - * equivalent byte sized hex value in R0(7:0). - * It accepts lowercase and uppercase ASCII Hex char inputs. - * Invalid inputs return -1 as the value -* On entry: - * R0: ASCII character - * On exit: - * R0: Hex value - */ - .global char2hex - -char2hex: - and r0, r0, #BYTE0 /* make sure that input is sane */ - cmp r0, #'0' - blo char2hex_error - cmp r0, #'9' - bls perform_char2hex - cmp r0, #'A' - blo char2hex_error - cmp r0, #'F' - bls perform_char2hex - cmp r0, #'a' - blo char2hex_error - cmp r0, #'f' - bhi char2hex_error - /* Validated Hex Char */ -perform_char2hex: - _char2hex r0 /* Return hex value in R0 */ - bx lr - -char2hex_error: - mov r0, #-1 /* Set Return value to Error value */ - bx lr - -/* byte2ascii_cont - * (Shared routine, does not perform sanity checks) - * On entry: - * R0: ASCII buffer pointer - * R1[7:0]: byte value - * On exit: - * R0: Address of next empty char slot in buffer - * R1: Destroyed - * - * This routine accepts an ASCII buffer pointer in R0 and a byte value in R1, - * and stores the ASCII equivalent byte value in the buffer pointed to by R0. - * Note: On return, R0 points to next empty char slot in buffer - */ -byte2ascii_cont: - stmfd sp!, {r2,r3,r4, lr} - lsl r2, r1, #24 /* Keep copy of input byte value R1[7:0], shifted to MSB R2[31:24] */ - mov r4, #2 /* Loop counter */ - _hex2char_lut r3 /* initialize LUT pointer */ -1: ror r2, r2, #28 /* Rotate MSNibble R2[31:28] into LSNibble position R2[3:0] */ - and r1, r2, #NIBBLE0 /* Mask out everything else, store Nibble in R1 */ - _hex2char_cont r1, r3 /* Convert nibble to ASCII char */ - strb r1, [r0], #1 - subs r4, r4, #1 /* decrement loop counter */ - bne 1b - ldmfd sp!, {r2,r3,r4, pc} - -/* byte2ascii - * On entry: - * R0: ASCII buffer pointer - * R1[7:0]: Byte value - * On exit: - * R0: Address of next empty char slot in buffer - * R1: Original Address of Buffer - * - * This routine accepts an ASCII buffer pointer in R0 and a byte value in R1, - * and stores the ASCII equivalent byte value in the buffer pointed to by R0. - * Note: On return, R0 points to the next empty char slot in buffer - */ - .global byte2ascii - -byte2ascii: - stmfd sp!, {r0, lr} /* Keep ASCII buffer pointer */ - and r1, #BYTE0 /* sanitize input */ - bl byte2ascii_cont - ldmfd sp!, {r1, pc} /* return original string pointer in R1 */ - -/* halfword2ascii_be - * Big Endian version of halfword2ascii conversion routine - * On entry: - * R0: ASCII buffer pointer - * R1[15:0]: Halfword value - * On exit: - * R0: Address of next empty char slot in buffer - * R1: Original Address of Buffer - * - * This routine accepts an ASCII buffer pointer in R0 and a halfword value in R1, - * and stores the ASCII equivalent halfword value in the buffer pointed to by R0. - * Note: On return, R0 points to the next empty char slot in buffer - */ - .global halfword2ascii_be -halfword2ascii_be: - stmfd sp!, {r0,r2,r3, lr} /* Keep ASCII buffer pointer */ - mov r3, #2 /* Loop Counter */ - mov r2, r1, lsl #16 /* copy of input halfword value R1[15:0], shifted to MSH R2[31:16] */ - b _conv_byte2ascii_be /* goto Byte conversion loop */ - -/* halfword2ascii_le - * Little Endian version of halfword2ascii conversion routine - * On entry: - * R0: ASCII buffer pointer - * R1[15:0]: Halfword value - * On exit: - * R0: Address of next empty char slot in buffer - * R1: Original Address of Buffer - * - * This routine accepts an ASCII buffer pointer in R0 and a halfword value in R1, - * and stores the ASCII equivalent halfword value in the buffer pointed to by R0. - * Note: On return, R0 points to the next empty char slot in buffer - */ - .global halfword2ascii_le -halfword2ascii_le: - stmfd sp!, {r0,r2,r3, lr} /* Keep ASCII buffer pointer */ - mov r3, #2 /* Loop Counter */ - b _conv_byte2ascii_le /* goto Byte conversion loop */ - - -/* word2ascii_be - * Big Endian version of word2ascii conversion routine - * On entry: - * R0: ASCII buffer pointer - * R1[31:0]: Word value - * On exit: - * R0: Address of next empty char slot in buffer - * R1: Original Address of Buffer - * - * This routine accepts an ASCII buffer pointer in R0 and a word value in R1, - * and stores the ASCII equivalent word value in the buffer pointed to by R0. - * Note: On return, R0 points to the next empty char slot in buffer - */ - .global word2ascii_be -word2ascii_be: - stmfd sp!, {r0,r2,r3, lr} /* Keep ASCII buffer pointer */ - mov r2, r1 /* copy of input word value R1[31:0] */ - mov r3, #4 /* Loop Counter */ - - /* Fall through to byte coversion loop */ - - -/* Big Endian Multibyte Convert: Rotate then convert */ -_conv_byte2ascii_be: - ror r2, r2, #24 /* Rotate MSB R2[31:24] into LSB position R2[7:0] */ - and r1, r2, #BYTE0 /* Copy byte value in R2[7:0] into R1 */ - bl byte2ascii_cont /* R0: next ASCII buffer location pointer, R1: destroyed */ - subs r3, r3, #1 - bne _conv_byte2ascii_be - ldmfd sp!, {r1,r2,r3, pc} - -/* word2ascii_le - * Little Endian version of word2ascii conversion routine - * On entry: - * R0: ASCII buffer pointer - * R1[31:0]: Word value - * On exit: - * R0: Address of next empty char slot in buffer - * R1: Original Address of Buffer - * - * This routine accepts an ASCII buffer pointer in R0 and a word value in R1, - * and stores the ASCII equivalent word value in the buffer pointed to by R0. - * Note: On return, R0 points to the next empty char slot in buffer - */ - .global word2ascii_le -word2ascii_le: - stmfd sp!, {r0,r2,r3, lr} /* Keep ASCII buffer pointer */ - mov r2, r1 /* copy of input word value R1[31:0] */ - mov r3, #4 /* Loop Counter */ - - /* Fall through to byte coversion loop */ - -/* Little Endian Multibyte Convert: Convert then rotate */ -_conv_byte2ascii_le: - and r1, r2, #BYTE0 /* Copy byte value in R2[7:0] into R1 */ - bl byte2ascii_cont /* R0: next ASCII buffer location pointer, R1: destroyed */ - ror r2, r2, #8 /* Rotate LSB+1 R2[15:8] into LSB position R2[7:0] */ - subs r3, r3, #1 - bne _conv_byte2ascii_le - ldmfd sp!, {r1,r2,r3, pc} - - -/* ascii2hex_varlen_be - * Big Endian version of ascii2hex_varlen conversion routine - * (There is no Little Endian Version) - * On entry: - * R0: ASCII buffer pointer - * On exit: - * R0: Hex value - * R1: Address of next char slot in buffer - * - * This routine accepts an ASCII buffer pointer in R0, - * and returns the hex value in R0 for up to 8 Hex characters. - * Note: On return, R1 points to the ASCII buffer location after the hex value chars. - */ - .global ascii2hex_varlen_be - -ascii2hex_varlen_be: - stmfd sp!, {r2,r3, lr} - mov r3, #CMD_REG_REGPARAMLEN /* Set max count to 8 (Max Register size) */ - mov r1, r0 /* Use R1 as ASCII buffer pointer */ - mov r2, #0 /* Initialize Cummulative Results */ -2: ldrb r0, [r1] /* Load ASCII char for Hex Value */ - bl char2hex /* on return, hex value in R0, -1 for error */ - cmp r0, #-1 - beq _exit_ascii2hex_varlen - orr r2, r0, r2, lsl #4 /* combined byte value */ - subs r3, r3, #1 /* Decrement Counter */ - add r1, r1, #1 /* Go to next char slot */ - bne 2b -_exit_ascii2hex_varlen: - mov r0, r2 /* Return results in R0 */ - ldmfd sp!, {r2,r3, pc} - - -/* ascii2byte - * On entry: - * R0: ASCII buffer pointer - * On exit: - * R0[7:0]: Byte value - * R1: Address of next char slot in buffer - * - * This routine accepts an ASCII buffer pointer in R0, - * and returns the byte value in R0[7:0]. - * Note: On return, R1 points to the ASCII buffer location after the current 2 chars. - * WARNING: This routine assumes that the input buffer was sanitized and contains valid Hex chars, - * otherwise it will return invalid results. - */ - .global ascii2byte - -ascii2byte: - stmfd sp!, {r2, lr} - mov r1, r0 /* Use R1 as ASCII buffer pointer */ - ldrb r0, [r1], #1 /* Load ASCII char for MSN */ - bl char2hex /* on return, hex value in R0, -1 for error (ignored) */ - mov r2, r0, lsl #4 /* Intermediate Results register */ - ldrb r0, [r1], #1 /* Load ASCII char for LSN */ - bl char2hex /* on return, hex value in R0, -1 for error (ignored) */ - orr r0, r2, r0 /* combined byte value */ - ldmfd sp!, {r2, pc} - -/* ascii2halfword_be - * Big Endian version of ascii2halfword conversion routine - * On entry: - * R0: ASCII buffer pointer - * On exit: - * R0[15:0]: Halfword value - * R1: Address of next char slot in buffer - * - * This routine accepts an ASCII buffer pointer in R0, - * and returns the Halfword value in R0[15:0]. - * Note: On return, R1 points to the ASCII buffer location after the current 4 chars. - * WARNING: This routine assumes that the input buffer was sanitized and contains valid Hex chars, - * otherwise it will return invalid results. - */ - .global ascii2halfword_be - -ascii2halfword_be: - stmfd sp!, {r2,r3, lr} - mov r3, #2 /* Loop counter */ - b _conv_ascii2byte_be - -/* ascii2halfword_le - * Little Endian version of ascii2halfword conversion routine - * On entry: - * R0: ASCII buffer pointer - * On exit: - * R0[15:0]: Halfword value - * R1: Address of next char slot in buffer - * - * This routine accepts an ASCII buffer pointer in R0, - * and returns the Halfword value in R0[15:0]. - * Note: On return, R1 points to the ASCII buffer location after the current 4 chars. - * WARNING: This routine assumes that the input buffer was sanitized and contains valid Hex chars, - * otherwise it will return invalid results. - */ - .global ascii2halfword_le - -ascii2halfword_le: - stmfd sp!, {r2,r3, lr} - mov r3, #2 /* Loop counter */ - b _conv_ascii2byte_le - - -/* ascii2word_be - * Big Endian version of ascii2word conversion routine - * On entry: - * R0: ASCII buffer pointer - * On exit: - * R0[31:0]: Word value - * R1: Address of next char slot in buffer - * - * This routine accepts an ASCII buffer pointer in R0, - * and returns the word value in R0[31:0]. - * Note: On return, R1 points to the ASCII buffer location after the current 8 chars. - * WARNING: This routine assumes that the input buffer was sanitized and contains valid Hex chars, - * otherwise it will return invalid results. - */ - .global ascii2word_be - -ascii2word_be: - stmfd sp!, {r2,r3, lr} - mov r3, #4 /* Loop counter */ - - /* Fall through to byte coversion loop */ - -_conv_ascii2byte_be: - teq r0, #0 - beq _exit_conv_ascii2byte_be /* exit if NULL pointer in R0 */ - mov r2, #0 /* Initialize Cummulative value */ -2: bl ascii2byte - orr r2, r0, r2, lsl #8 /* Merge current byte with cummulative value */ - mov r0, r1 /* Copy next char pointer to R0 for next byte */ - subs r3, r3, #1 - bne 2b - mov r0, r2 /* Copy it to R0 as return value */ - -_exit_conv_ascii2byte_be: - ldmfd sp!, {r2,r3, pc} /* return hex value in R0 */ - -/* ascii2word_le - * Litle Endian version of ascii2word conversion routine - * On entry: - * R0: ASCII buffer pointer - * On exit: - * R0[31:0]: Word value - * R1: Address of next char slot in buffer - * - * This routine accepts an ASCII buffer pointer in R0, - * and returns the word value in R0[31:0]. - * Note: On return, R1 points to the ASCII buffer location after the current 8 chars. - * WARNING: This routine assumes that the input buffer was sanitized and contains valid Hex chars, - * otherwise it will return invalid results. - */ - .global ascii2word_le - -ascii2word_le: - stmfd sp!, {r2,r3, lr} - mov r3, #4 /* Loop counter */ - - /* Fall through to byte coversion loop */ - -_conv_ascii2byte_le: - teq r0, #0 - beq _exit_conv_ascii2byte_le /* exit if NULL pointer in R0 */ - push {r3} /* Need to keep couter for final value adjustment */ - mov r2, #0 /* Initialize Cummulative value */ -2: bl ascii2byte - orr r2, r0, r2, ror #8 /* Merge current byte with cummulative value */ - mov r0, r1 /* Copy next char pointer to R0 for next byte */ - subs r3, r3, #1 - bne 2b - /* Cummulative value done, need to rotate it into the correct position for return value */ - pop {r3} /* retrieve counter */ - rsb r3, r3, #5 /* 5 - count */ - lsl r3, r3, #3 /* [(5-count) x 8] bits to rotate */ - mov r0, r2, ror r3 /* Copy it to R0 as return value */ - -_exit_conv_ascii2byte_le: - ldmfd sp!, {r2,r3, pc} /* return hex value in R0 */ - - - - /* Debugger Communications Routines * It does not make sense to pass information from the Debugger Module to the Comm. link one character * at a time, especially if we're not using a native serial interface (e.g., EIA-232). Consequently diff --git a/Debugger/debug_hexutils.S b/Debugger/debug_hexutils.S new file mode 100644 index 0000000..d54445b --- /dev/null +++ b/Debugger/debug_hexutils.S @@ -0,0 +1,457 @@ +/** @file debug_hexutils.S + * @brief GDB hexadecimal conversion utility routines + * + */ + +/* Copyright (C) 2007-2011 the NxOS developers + * + * Module Developed by: TC Wan + * + * See AUTHORS for a full list of the developers. + * + * See COPYING for redistribution license + * + */ + + +#define __ASSEMBLY__ + +#include "debug_internals.h" + +.data +.align 4 + +hex2char_lut: + .ascii "0123456789ABCDEF" + +/* Macros + */ + + +/* _hex2char_lut + * Internal routine to intialize the LUT address pointer + */ + .macro _hex2char_lut addrptr + ldr \addrptr, =hex2char_lut + .endm + +/* _hex2char_cont + * Internal routine that assumes that the LUT has been loaded. + * This macro accepts a byte sized hex value as a parameter register(7:0) and returns the + * ASCII equivalent in in the same register(7:0) + * The second parameter is the LUT address pointer register to use (assumed to be initialized) + * WARNING: Assumes that the value in register is sanity checked before invoking macro + */ + .macro _hex2char_cont reg, addrptr + ldrb \reg, [\addrptr, \reg] + .endm + +/* _hex2char + * This macro accepts a byte sized hex value as a parameter register(7:0) and returns the + * ASCII equivalent in in the same register(7:0) + * The second parameter is the LUT address pointer register to use (register content is destroyed) + * WARNING: Assumes that the value in register is sanity checked before invoking macro + */ + .macro _hex2char reg, addrptr + _hex2char_lut \addrptr + _hex2char_cont \reg, \addrptr + .endm + +/* _char2hex + * This macro accepts an ASCII char as a parameter register(7:0) and returns the + * equivalent byte sized hex value in in the same register(7:0) + * WARNING: Assumes that the char in register is a valid hex char before invoking macro + */ + .macro _char2hex reg + cmp \reg, #'A' /* If Alpha */ + bichs \reg, \reg, #ASCII_LOWER2UPPER_MASK /* Convert to Uppercase */ + subhs \reg, \reg, #7 /* Adjustment to allow for subtraction with 0x30 */ + sub \reg, \reg, #0x30 /* get final hex value */ + .endm + + +.code 32 +.text +.align 4 + + +/* Utility Routines + * GDB requires command parameters to be specified as Big Endian values. + * However, the read/write register command expect the register contents to be specified in target byte order. + * Hence we need both versions of multibyte conversion routines for word sized values. + */ + +/* hex2char + * This routine accepts a byte sized hex value in R0(7:0) and returns the + * ASCII equivalent in R0(7:0) + */ + .global hex2char + +hex2char: + stmfd sp!, {r1,lr} + and r0, #NIBBLE0 /* make sure that input is sane */ + _hex2char r0, r1 + ldmfd sp!, {r1,pc} + +/* char2hex + * This routine accepts an ASCII character in R0(7:0) and returns the + * equivalent byte sized hex value in R0(7:0). + * It accepts lowercase and uppercase ASCII Hex char inputs. + * Invalid inputs return -1 as the value +* On entry: + * R0: ASCII character + * On exit: + * R0: Hex value + */ + .global char2hex + +char2hex: + and r0, r0, #BYTE0 /* make sure that input is sane */ + cmp r0, #'0' + blo char2hex_error + cmp r0, #'9' + bls perform_char2hex + cmp r0, #'A' + blo char2hex_error + cmp r0, #'F' + bls perform_char2hex + cmp r0, #'a' + blo char2hex_error + cmp r0, #'f' + bhi char2hex_error + /* Validated Hex Char */ +perform_char2hex: + _char2hex r0 /* Return hex value in R0 */ + bx lr + +char2hex_error: + mov r0, #-1 /* Set Return value to Error value */ + bx lr + +/* byte2ascii_cont + * (Shared routine, does not perform sanity checks) + * On entry: + * R0: ASCII buffer pointer + * R1[7:0]: byte value + * On exit: + * R0: Address of next empty char slot in buffer + * R1: Destroyed + * + * This routine accepts an ASCII buffer pointer in R0 and a byte value in R1, + * and stores the ASCII equivalent byte value in the buffer pointed to by R0. + * Note: On return, R0 points to next empty char slot in buffer + */ +byte2ascii_cont: + stmfd sp!, {r2,r3,r4, lr} + lsl r2, r1, #24 /* Keep copy of input byte value R1[7:0], shifted to MSB R2[31:24] */ + mov r4, #2 /* Loop counter */ + _hex2char_lut r3 /* initialize LUT pointer */ +1: ror r2, r2, #28 /* Rotate MSNibble R2[31:28] into LSNibble position R2[3:0] */ + and r1, r2, #NIBBLE0 /* Mask out everything else, store Nibble in R1 */ + _hex2char_cont r1, r3 /* Convert nibble to ASCII char */ + strb r1, [r0], #1 + subs r4, r4, #1 /* decrement loop counter */ + bne 1b + ldmfd sp!, {r2,r3,r4, pc} + +/* byte2ascii + * On entry: + * R0: ASCII buffer pointer + * R1[7:0]: Byte value + * On exit: + * R0: Address of next empty char slot in buffer + * R1: Original Address of Buffer + * + * This routine accepts an ASCII buffer pointer in R0 and a byte value in R1, + * and stores the ASCII equivalent byte value in the buffer pointed to by R0. + * Note: On return, R0 points to the next empty char slot in buffer + */ + .global byte2ascii + +byte2ascii: + stmfd sp!, {r0, lr} /* Keep ASCII buffer pointer */ + and r1, #BYTE0 /* sanitize input */ + bl byte2ascii_cont + ldmfd sp!, {r1, pc} /* return original string pointer in R1 */ + +/* halfword2ascii_be + * Big Endian version of halfword2ascii conversion routine + * On entry: + * R0: ASCII buffer pointer + * R1[15:0]: Halfword value + * On exit: + * R0: Address of next empty char slot in buffer + * R1: Original Address of Buffer + * + * This routine accepts an ASCII buffer pointer in R0 and a halfword value in R1, + * and stores the ASCII equivalent halfword value in the buffer pointed to by R0. + * Note: On return, R0 points to the next empty char slot in buffer + */ + .global halfword2ascii_be +halfword2ascii_be: + stmfd sp!, {r0,r2,r3, lr} /* Keep ASCII buffer pointer */ + mov r3, #2 /* Loop Counter */ + mov r2, r1, lsl #16 /* copy of input halfword value R1[15:0], shifted to MSH R2[31:16] */ + b _conv_byte2ascii_be /* goto Byte conversion loop */ + +/* halfword2ascii_le + * Little Endian version of halfword2ascii conversion routine + * On entry: + * R0: ASCII buffer pointer + * R1[15:0]: Halfword value + * On exit: + * R0: Address of next empty char slot in buffer + * R1: Original Address of Buffer + * + * This routine accepts an ASCII buffer pointer in R0 and a halfword value in R1, + * and stores the ASCII equivalent halfword value in the buffer pointed to by R0. + * Note: On return, R0 points to the next empty char slot in buffer + */ + .global halfword2ascii_le +halfword2ascii_le: + stmfd sp!, {r0,r2,r3, lr} /* Keep ASCII buffer pointer */ + mov r3, #2 /* Loop Counter */ + b _conv_byte2ascii_le /* goto Byte conversion loop */ + + +/* word2ascii_be + * Big Endian version of word2ascii conversion routine + * On entry: + * R0: ASCII buffer pointer + * R1[31:0]: Word value + * On exit: + * R0: Address of next empty char slot in buffer + * R1: Original Address of Buffer + * + * This routine accepts an ASCII buffer pointer in R0 and a word value in R1, + * and stores the ASCII equivalent word value in the buffer pointed to by R0. + * Note: On return, R0 points to the next empty char slot in buffer + */ + .global word2ascii_be +word2ascii_be: + stmfd sp!, {r0,r2,r3, lr} /* Keep ASCII buffer pointer */ + mov r2, r1 /* copy of input word value R1[31:0] */ + mov r3, #4 /* Loop Counter */ + + /* Fall through to byte coversion loop */ + + +/* Big Endian Multibyte Convert: Rotate then convert */ +_conv_byte2ascii_be: + ror r2, r2, #24 /* Rotate MSB R2[31:24] into LSB position R2[7:0] */ + and r1, r2, #BYTE0 /* Copy byte value in R2[7:0] into R1 */ + bl byte2ascii_cont /* R0: next ASCII buffer location pointer, R1: destroyed */ + subs r3, r3, #1 + bne _conv_byte2ascii_be + ldmfd sp!, {r1,r2,r3, pc} + +/* word2ascii_le + * Little Endian version of word2ascii conversion routine + * On entry: + * R0: ASCII buffer pointer + * R1[31:0]: Word value + * On exit: + * R0: Address of next empty char slot in buffer + * R1: Original Address of Buffer + * + * This routine accepts an ASCII buffer pointer in R0 and a word value in R1, + * and stores the ASCII equivalent word value in the buffer pointed to by R0. + * Note: On return, R0 points to the next empty char slot in buffer + */ + .global word2ascii_le +word2ascii_le: + stmfd sp!, {r0,r2,r3, lr} /* Keep ASCII buffer pointer */ + mov r2, r1 /* copy of input word value R1[31:0] */ + mov r3, #4 /* Loop Counter */ + + /* Fall through to byte coversion loop */ + +/* Little Endian Multibyte Convert: Convert then rotate */ +_conv_byte2ascii_le: + and r1, r2, #BYTE0 /* Copy byte value in R2[7:0] into R1 */ + bl byte2ascii_cont /* R0: next ASCII buffer location pointer, R1: destroyed */ + ror r2, r2, #8 /* Rotate LSB+1 R2[15:8] into LSB position R2[7:0] */ + subs r3, r3, #1 + bne _conv_byte2ascii_le + ldmfd sp!, {r1,r2,r3, pc} + + +/* ascii2hex_varlen_be + * Big Endian version of ascii2hex_varlen conversion routine + * (There is no Little Endian Version) + * On entry: + * R0: ASCII buffer pointer + * On exit: + * R0: Hex value + * R1: Address of next char slot in buffer + * + * This routine accepts an ASCII buffer pointer in R0, + * and returns the hex value in R0 for up to 8 Hex characters. + * Note: On return, R1 points to the ASCII buffer location after the hex value chars. + */ + .global ascii2hex_varlen_be + +ascii2hex_varlen_be: + stmfd sp!, {r2,r3, lr} + mov r3, #CMD_REG_REGPARAMLEN /* Set max count to 8 (Max Register size) */ + mov r1, r0 /* Use R1 as ASCII buffer pointer */ + mov r2, #0 /* Initialize Cummulative Results */ +2: ldrb r0, [r1] /* Load ASCII char for Hex Value */ + bl char2hex /* on return, hex value in R0, -1 for error */ + cmp r0, #-1 + beq _exit_ascii2hex_varlen + orr r2, r0, r2, lsl #4 /* combined byte value */ + subs r3, r3, #1 /* Decrement Counter */ + add r1, r1, #1 /* Go to next char slot */ + bne 2b +_exit_ascii2hex_varlen: + mov r0, r2 /* Return results in R0 */ + ldmfd sp!, {r2,r3, pc} + + +/* ascii2byte + * On entry: + * R0: ASCII buffer pointer + * On exit: + * R0[7:0]: Byte value + * R1: Address of next char slot in buffer + * + * This routine accepts an ASCII buffer pointer in R0, + * and returns the byte value in R0[7:0]. + * Note: On return, R1 points to the ASCII buffer location after the current 2 chars. + * WARNING: This routine assumes that the input buffer was sanitized and contains valid Hex chars, + * otherwise it will return invalid results. + */ + .global ascii2byte + +ascii2byte: + stmfd sp!, {r2, lr} + mov r1, r0 /* Use R1 as ASCII buffer pointer */ + ldrb r0, [r1], #1 /* Load ASCII char for MSN */ + bl char2hex /* on return, hex value in R0, -1 for error (ignored) */ + mov r2, r0, lsl #4 /* Intermediate Results register */ + ldrb r0, [r1], #1 /* Load ASCII char for LSN */ + bl char2hex /* on return, hex value in R0, -1 for error (ignored) */ + orr r0, r2, r0 /* combined byte value */ + ldmfd sp!, {r2, pc} + +/* ascii2halfword_be + * Big Endian version of ascii2halfword conversion routine + * On entry: + * R0: ASCII buffer pointer + * On exit: + * R0[15:0]: Halfword value + * R1: Address of next char slot in buffer + * + * This routine accepts an ASCII buffer pointer in R0, + * and returns the Halfword value in R0[15:0]. + * Note: On return, R1 points to the ASCII buffer location after the current 4 chars. + * WARNING: This routine assumes that the input buffer was sanitized and contains valid Hex chars, + * otherwise it will return invalid results. + */ + .global ascii2halfword_be + +ascii2halfword_be: + stmfd sp!, {r2,r3, lr} + mov r3, #2 /* Loop counter */ + b _conv_ascii2byte_be + +/* ascii2halfword_le + * Little Endian version of ascii2halfword conversion routine + * On entry: + * R0: ASCII buffer pointer + * On exit: + * R0[15:0]: Halfword value + * R1: Address of next char slot in buffer + * + * This routine accepts an ASCII buffer pointer in R0, + * and returns the Halfword value in R0[15:0]. + * Note: On return, R1 points to the ASCII buffer location after the current 4 chars. + * WARNING: This routine assumes that the input buffer was sanitized and contains valid Hex chars, + * otherwise it will return invalid results. + */ + .global ascii2halfword_le + +ascii2halfword_le: + stmfd sp!, {r2,r3, lr} + mov r3, #2 /* Loop counter */ + b _conv_ascii2byte_le + + +/* ascii2word_be + * Big Endian version of ascii2word conversion routine + * On entry: + * R0: ASCII buffer pointer + * On exit: + * R0[31:0]: Word value + * R1: Address of next char slot in buffer + * + * This routine accepts an ASCII buffer pointer in R0, + * and returns the word value in R0[31:0]. + * Note: On return, R1 points to the ASCII buffer location after the current 8 chars. + * WARNING: This routine assumes that the input buffer was sanitized and contains valid Hex chars, + * otherwise it will return invalid results. + */ + .global ascii2word_be + +ascii2word_be: + stmfd sp!, {r2,r3, lr} + mov r3, #4 /* Loop counter */ + + /* Fall through to byte coversion loop */ + +_conv_ascii2byte_be: + teq r0, #0 + beq _exit_conv_ascii2byte_be /* exit if NULL pointer in R0 */ + mov r2, #0 /* Initialize Cummulative value */ +2: bl ascii2byte + orr r2, r0, r2, lsl #8 /* Merge current byte with cummulative value */ + mov r0, r1 /* Copy next char pointer to R0 for next byte */ + subs r3, r3, #1 + bne 2b + mov r0, r2 /* Copy it to R0 as return value */ + +_exit_conv_ascii2byte_be: + ldmfd sp!, {r2,r3, pc} /* return hex value in R0 */ + +/* ascii2word_le + * Litle Endian version of ascii2word conversion routine + * On entry: + * R0: ASCII buffer pointer + * On exit: + * R0[31:0]: Word value + * R1: Address of next char slot in buffer + * + * This routine accepts an ASCII buffer pointer in R0, + * and returns the word value in R0[31:0]. + * Note: On return, R1 points to the ASCII buffer location after the current 8 chars. + * WARNING: This routine assumes that the input buffer was sanitized and contains valid Hex chars, + * otherwise it will return invalid results. + */ + .global ascii2word_le + +ascii2word_le: + stmfd sp!, {r2,r3, lr} + mov r3, #4 /* Loop counter */ + + /* Fall through to byte coversion loop */ + +_conv_ascii2byte_le: + teq r0, #0 + beq _exit_conv_ascii2byte_le /* exit if NULL pointer in R0 */ + push {r3} /* Need to keep couter for final value adjustment */ + mov r2, #0 /* Initialize Cummulative value */ +2: bl ascii2byte + orr r2, r0, r2, ror #8 /* Merge current byte with cummulative value */ + mov r0, r1 /* Copy next char pointer to R0 for next byte */ + subs r3, r3, #1 + bne 2b + /* Cummulative value done, need to rotate it into the correct position for return value */ + pop {r3} /* retrieve counter */ + rsb r3, r3, #5 /* 5 - count */ + lsl r3, r3, #3 /* [(5-count) x 8] bits to rotate */ + mov r0, r2, ror r3 /* Copy it to R0 as return value */ + +_exit_conv_ascii2byte_le: + ldmfd sp!, {r2,r3, pc} /* return hex value in R0 */ + -- cgit v1.2.3