1// picoChip ASM file 2// 3// Support for 16-bit signed division/modulus. 4// 5// Copyright (C) 2003, 2004, 2005, 2008, 2009 Free Software Foundation, Inc. 6// Contributed by picoChip Designs Ltd. 7// Maintained by Daniel Towner (daniel.towner@picochip.com) 8// 9// This file is free software; you can redistribute it and/or modify it 10// under the terms of the GNU General Public License as published by the 11// Free Software Foundation; either version 3, or (at your option) any 12// later version. 13// 14// This file is distributed in the hope that it will be useful, but 15// WITHOUT ANY WARRANTY; without even the implied warranty of 16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17// General Public License for more details. 18// 19// Under Section 7 of GPL version 3, you are granted additional 20// permissions described in the GCC Runtime Library Exception, version 21// 3.1, as published by the Free Software Foundation. 22// 23// You should have received a copy of the GNU General Public License and 24// a copy of the GCC Runtime Library Exception along with this program; 25// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 26// <http://www.gnu.org/licenses/>. 27 28.section .text 29 30.align 8 31.global __divmodhi4 32__divmodhi4: 33_picoMark_FUNCTION_BEGIN= 34 35// picoChip Function Prologue : &__divmodhi4 = 4 bytes 36 37 // 16-bit signed division. Most of the special cases are dealt 38 // with by the 15-bit signed division library (e.g., division by 39 // zero, division by 1, and so on). This wrapper simply inverts 40 // any negative inputs, calls the 15-bit library, and flips any 41 // results as necessary. The 42 // only special cases to be handled here are where either the 43 // divisor or the dividend are the maximum negative values. 44 45 // Encode r5 with a bit pattern which indicates whether the 46 // outputs of the division must be negated. The MSB will be set 47 // to the sign of the dividend (which controls the remainder's 48 // sign), while the LSB will store the XOR of the two signs, 49 // which indicates the quotient's sign. R5 is not modified by the 50 // 15-bit divmod routine. 51 sub.0 r1,16#8000#,r15 \ asr.1 r0,15,r4 52 beq divisorIsLargestNegative \ lsr.0 r1,15,r3 53=-> sub.0 r0,16#8000#,r15 \ xor.1 r3,r4,r5 54 55 // Handle least negative dividend with a special case. Note that the 56 // absolute value of the divisor is also computed here. 57 add.0 [asr r1,15],r1,r3 \ beq dividendIsLargestNegative 58=-> xor.0 [asr r1,15],r3,r1 \ stw lr,(fp)-1 59 60 // Compute the absolute value of the dividend, and call the main 61 // divide routine. 62 add.0 r4,r0,r2 \ jl (&__divmod15) // fn_call &__divmod15 63=-> xor.0 r4,r2,r0 64 65handleNegatedResults: 66 // Speculatively store the negation of the results. 67 sub.0 0,r0,r2 \ sub.1 0,r1,r3 68 69 // Does the quotient need negating? The LSB indicates this. 70 and.0 r5,1,r15 \ ldw (fp)-1,lr 71 copyne r2,r0 72 73 asr.0 r5,15,r15 \ jr (lr) 74=-> copyne r3,r1 75 76dividendIsLargestNegative: 77 78 // Divide the constant -32768. Use the Hacker's Delight 79 // algorithm (i.e., ((dividend / 2) / divisor) * 2) gives 80 // approximate answer). This code is a special case, so no 81 // great effort is made to make it fast, only to make it 82 // small. 83 84 lsr.0 r0,1,r0 \ jl (&__divmod15) // fn_call &__divmod15 85=-> stw r1,(fp)-2 86 87 // Load the original divisor, and compute the new quotient and 88 // remainder. 89 lsl.0 r0,1,r0 \ ldw (fp)-2,r3 90 lsl.0 r1,1,r1 // Fill stall slot 91 92 // The error in the quotient is 0 or 1. The error can be determined 93 // by comparing the remainder to the original divisor. If the 94 // remainder is bigger, then an error of 1 has been introduced, 95 // which must be fixed. 96 sub.0 r1,r3,r15 97 blo noCompensationForError 98=-> nop 99 add.0 r0,1,r0 \ sub.1 r1,r3,r1 100noCompensationForError: 101 bra handleNegatedResults 102=-> nop 103 104divisorIsLargestNegative: 105 // The flags indicate whether the dividend is also the maximum negative 106 copy.0 r0,r1 \ copy.1 0,r0 107 copyeq r0,r1 \ jr (lr) 108=-> copyeq 1,r0 109 110_picoMark_FUNCTION_END= 111// picoChip Function Epilogue : __divmodhi4 112 113 114//============================================================================ 115// All DWARF information between this marker, and the END OF DWARF 116// marker should be included in the source file. Search for 117// FUNCTION_STACK_SIZE_GOES_HERE and FUNCTION NAME GOES HERE, and 118// provide the relevent information. Add markers called 119// _picoMark_FUNCTION_BEGIN and _picoMark_FUNCTION_END around the 120// function in question. 121//============================================================================ 122 123//============================================================================ 124// Frame information. 125//============================================================================ 126 127.section .debug_frame 128_picoMark_DebugFrame= 129 130// Common CIE header. 131.unalignedInitLong _picoMark_CieEnd-_picoMark_CieBegin 132_picoMark_CieBegin= 133.unalignedInitLong 0xffffffff 134.initByte 0x1 // CIE Version 135.ascii 16#0# // CIE Augmentation 136.uleb128 0x1 // CIE Code Alignment Factor 137.sleb128 2 // CIE Data Alignment Factor 138.initByte 0xc // CIE RA Column 139.initByte 0xc // DW_CFA_def_cfa 140.uleb128 0xd 141.uleb128 0x0 142.align 2 143_picoMark_CieEnd= 144 145// FDE 146_picoMark_LSFDE0I900821033007563= 147.unalignedInitLong _picoMark_FdeEnd-_picoMark_FdeBegin 148_picoMark_FdeBegin= 149.unalignedInitLong _picoMark_DebugFrame // FDE CIE offset 150.unalignedInitWord _picoMark_FUNCTION_BEGIN // FDE initial location 151.unalignedInitWord _picoMark_FUNCTION_END-_picoMark_FUNCTION_BEGIN 152.initByte 0xe // DW_CFA_def_cfa_offset 153.uleb128 0x4 // <-- FUNCTION_STACK_SIZE_GOES_HERE 154.initByte 0x4 // DW_CFA_advance_loc4 155.unalignedInitLong _picoMark_FUNCTION_END-_picoMark_FUNCTION_BEGIN 156.initByte 0xe // DW_CFA_def_cfa_offset 157.uleb128 0x0 158.align 2 159_picoMark_FdeEnd= 160 161//============================================================================ 162// Abbrevation information. 163//============================================================================ 164 165.section .debug_abbrev 166_picoMark_ABBREVIATIONS= 167 168.section .debug_abbrev 169 .uleb128 0x1 // (abbrev code) 170 .uleb128 0x11 // (TAG: DW_TAG_compile_unit) 171 .initByte 0x1 // DW_children_yes 172 .uleb128 0x10 // (DW_AT_stmt_list) 173 .uleb128 0x6 // (DW_FORM_data4) 174 .uleb128 0x12 // (DW_AT_high_pc) 175 .uleb128 0x1 // (DW_FORM_addr) 176 .uleb128 0x11 // (DW_AT_low_pc) 177 .uleb128 0x1 // (DW_FORM_addr) 178 .uleb128 0x25 // (DW_AT_producer) 179 .uleb128 0x8 // (DW_FORM_string) 180 .uleb128 0x13 // (DW_AT_language) 181 .uleb128 0x5 // (DW_FORM_data2) 182 .uleb128 0x3 // (DW_AT_name) 183 .uleb128 0x8 // (DW_FORM_string) 184.initByte 0x0 185.initByte 0x0 186 187 .uleb128 0x2 ;# (abbrev code) 188 .uleb128 0x2e ;# (TAG: DW_TAG_subprogram) 189.initByte 0x0 ;# DW_children_no 190 .uleb128 0x3 ;# (DW_AT_name) 191 .uleb128 0x8 ;# (DW_FORM_string) 192 .uleb128 0x11 ;# (DW_AT_low_pc) 193 .uleb128 0x1 ;# (DW_FORM_addr) 194 .uleb128 0x12 ;# (DW_AT_high_pc) 195 .uleb128 0x1 ;# (DW_FORM_addr) 196.initByte 0x0 197.initByte 0x0 198 199.initByte 0x0 200 201//============================================================================ 202// Line information. DwarfLib requires this to be present, but it can 203// be empty. 204//============================================================================ 205 206.section .debug_line 207_picoMark_LINES= 208 209//============================================================================ 210// Debug Information 211//============================================================================ 212.section .debug_info 213 214//Fixed header. 215.unalignedInitLong _picoMark_DEBUG_INFO_END-_picoMark_DEBUG_INFO_BEGIN 216_picoMark_DEBUG_INFO_BEGIN= 217.unalignedInitWord 0x2 218.unalignedInitLong _picoMark_ABBREVIATIONS 219.initByte 0x2 220 221// Compile unit information. 222.uleb128 0x1 // (DIE 0xb) DW_TAG_compile_unit) 223.unalignedInitLong _picoMark_LINES 224.unalignedInitWord _picoMark_FUNCTION_END 225.unalignedInitWord _picoMark_FUNCTION_BEGIN 226// Producer is `picoChip' 227.ascii 16#70# 16#69# 16#63# 16#6f# 16#43# 16#68# 16#69# 16#70# 16#00# 228.unalignedInitWord 0xcafe // ASM language 229.ascii 16#0# // Name. DwarfLib expects this to be present. 230 231.uleb128 0x2 ;# (DIE DW_TAG_subprogram) 232 233// FUNCTION NAME GOES HERE. Use `echo name | od -t x1' to get the hex. Each hex 234// digit is specified using the format 16#XX# 235.ascii 16#5f# 16#64# 16#69# 16#76# 16#6d# 16#6f# 16#64# 16#68# 16#69# 16#34# 16#0# // Function name `_divmodhi4' 236.unalignedInitWord _picoMark_FUNCTION_BEGIN // DW_AT_low_pc 237.unalignedInitWord _picoMark_FUNCTION_END // DW_AT_high_pc 238 239.initByte 0x0 // end of compile unit children. 240 241_picoMark_DEBUG_INFO_END= 242 243//============================================================================ 244// END OF DWARF 245//============================================================================ 246.section .endFile 247