1// picoChip ASM file 2// 3// Support for 16-bit unsigned 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.global __udivmodhi4 31__udivmodhi4: 32_picoMark_FUNCTION_BEGIN= 33 34// picoChip Function Prologue : &__udivmodhi4 = 6 bytes 35 36 // 16-bit unsigned division. The divstep function is only capable of 37 // handling 15-bit division (plus a sign to give 16-bits). It is not 38 // capable of handling unsigned division directly. Instead, take 39 // advantage of the special property that 40 // ((divisor / 2) / dividend) * 2 will be almost good enough. The 41 // error in the result is only 0 or 1, and this can be easily 42 // tested and corrected. A full description of the algorithm can 43 // be found in `Hacker's Delight', by Henry Warren, page 146. 44 45 // Input: 46 // r0 - dividend 47 // r1 - divisor 48 // Output: 49 // r0 - quotient 50 // r1 - remainder 51 52 // Note that the lr, and original inputs are speculatively saved. They 53 // will only be restored if the 15-bit division function is called. 54 55 sub.0 r1,0,r15 \ stl r[0:1],(fp)-1 56 bge divisorIs15bit 57=-> sub.0 r0,r1,r2 \ stw lr,(fp)-3 58 59 // The divisor is >= 2^15. 60 bhs quotientIs1 61 62 // The dividend < divisor. The quotient is thus 0, and the 63 // remainder is the dividend. 64 copy.0 r0,r1 \ jr (lr) 65=-> copy.0 0,r0 66 67quotientIs1: 68 // The dividend >= divisor. The quotient is thus 1, and the 69 // remainder can be computed directly by subtraction (i.e., the 70 // result of the comparison already performed to branch here). 71 jr (lr) \ copy.0 r2,r1 72=-> copy.0 1,r0 73 74divisorIs15bit: 75 // The divisor is < 2^15. 76 77 // Divide the original dividend by 2, and call the 15-bit division. 78 // Note that the original dividend is stored in r5, which is 79 // known to be unused by the called function, so that 80 // a memory stall isn't introduced immediately after the 81 // function returns, to reload this value from memory. 82 83 jl (&__divmod15) \ copy.0 r0,r5 // fn_call &__divmod15 84=-> lsr.0 r0,1,r0 85 86 // Compute the new quotient and remainder by multiplying them by 2. 87 // The remainder will be 1 out, if the original dividend was odd. 88 and.0 r5,1,r5 \ ldl (fp)-1,r[2:3] 89 add.0 [lsl r1,1],r5,r1 \ lsl.1 r0,1,r0 90 91 // The error in the quotient is 0 or 1. The error can be determined 92 // by comparing the remainder to the original divisor. If the 93 // remainder is bigger, then an error of 1 has been introduced. 94 sub.0 r1,r3,r15 \ ldw (fp)-3,lr 95 blo noCompensation 96=-> nop 97 add.0 r0,1,r0 \ sub.1 r1,r3,r1 98noCompensation: 99 jr (lr) 100 101_picoMark_FUNCTION_END= 102// picoChip Function Epilogue : udivmodhi4 103 104 105//============================================================================ 106// All DWARF information between this marker, and the END OF DWARF 107// marker should be included in the source file. Search for 108// FUNCTION_STACK_SIZE_GOES_HERE and FUNCTION NAME GOES HERE, and 109// provide the relevent information. Add markers called 110// _picoMark_FUNCTION_BEGIN and _picoMark_FUNCTION_END around the 111// function in question. 112//============================================================================ 113 114//============================================================================ 115// Frame information. 116//============================================================================ 117 118.section .debug_frame 119_picoMark_DebugFrame= 120 121// Common CIE header. 122.unalignedInitLong _picoMark_CieEnd-_picoMark_CieBegin 123_picoMark_CieBegin= 124.unalignedInitLong 0xffffffff 125.initByte 0x1 // CIE Version 126.ascii 16#0# // CIE Augmentation 127.uleb128 0x1 // CIE Code Alignment Factor 128.sleb128 2 // CIE Data Alignment Factor 129.initByte 0xc // CIE RA Column 130.initByte 0xc // DW_CFA_def_cfa 131.uleb128 0xd 132.uleb128 0x0 133.align 2 134_picoMark_CieEnd= 135 136// FDE 137_picoMark_LSFDE0I900821033007563= 138.unalignedInitLong _picoMark_FdeEnd-_picoMark_FdeBegin 139_picoMark_FdeBegin= 140.unalignedInitLong _picoMark_DebugFrame // FDE CIE offset 141.unalignedInitWord _picoMark_FUNCTION_BEGIN // FDE initial location 142.unalignedInitWord _picoMark_FUNCTION_END-_picoMark_FUNCTION_BEGIN 143.initByte 0xe // DW_CFA_def_cfa_offset 144.uleb128 0x6 // <-- FUNCTION_STACK_SIZE_GOES_HERE 145.initByte 0x4 // DW_CFA_advance_loc4 146.unalignedInitLong _picoMark_FUNCTION_END-_picoMark_FUNCTION_BEGIN 147.initByte 0xe // DW_CFA_def_cfa_offset 148.uleb128 0x0 149.align 2 150_picoMark_FdeEnd= 151 152//============================================================================ 153// Abbrevation information. 154//============================================================================ 155 156.section .debug_abbrev 157_picoMark_ABBREVIATIONS= 158 159.section .debug_abbrev 160 .uleb128 0x1 // (abbrev code) 161 .uleb128 0x11 // (TAG: DW_TAG_compile_unit) 162 .initByte 0x1 // DW_children_yes 163 .uleb128 0x10 // (DW_AT_stmt_list) 164 .uleb128 0x6 // (DW_FORM_data4) 165 .uleb128 0x12 // (DW_AT_high_pc) 166 .uleb128 0x1 // (DW_FORM_addr) 167 .uleb128 0x11 // (DW_AT_low_pc) 168 .uleb128 0x1 // (DW_FORM_addr) 169 .uleb128 0x25 // (DW_AT_producer) 170 .uleb128 0x8 // (DW_FORM_string) 171 .uleb128 0x13 // (DW_AT_language) 172 .uleb128 0x5 // (DW_FORM_data2) 173 .uleb128 0x3 // (DW_AT_name) 174 .uleb128 0x8 // (DW_FORM_string) 175.initByte 0x0 176.initByte 0x0 177 178 .uleb128 0x2 ;# (abbrev code) 179 .uleb128 0x2e ;# (TAG: DW_TAG_subprogram) 180.initByte 0x0 ;# DW_children_no 181 .uleb128 0x3 ;# (DW_AT_name) 182 .uleb128 0x8 ;# (DW_FORM_string) 183 .uleb128 0x11 ;# (DW_AT_low_pc) 184 .uleb128 0x1 ;# (DW_FORM_addr) 185 .uleb128 0x12 ;# (DW_AT_high_pc) 186 .uleb128 0x1 ;# (DW_FORM_addr) 187.initByte 0x0 188.initByte 0x0 189 190.initByte 0x0 191 192//============================================================================ 193// Line information. DwarfLib requires this to be present, but it can 194// be empty. 195//============================================================================ 196 197.section .debug_line 198_picoMark_LINES= 199 200//============================================================================ 201// Debug Information 202//============================================================================ 203.section .debug_info 204 205//Fixed header. 206.unalignedInitLong _picoMark_DEBUG_INFO_END-_picoMark_DEBUG_INFO_BEGIN 207_picoMark_DEBUG_INFO_BEGIN= 208.unalignedInitWord 0x2 209.unalignedInitLong _picoMark_ABBREVIATIONS 210.initByte 0x2 211 212// Compile unit information. 213.uleb128 0x1 // (DIE 0xb) DW_TAG_compile_unit) 214.unalignedInitLong _picoMark_LINES 215.unalignedInitWord _picoMark_FUNCTION_END 216.unalignedInitWord _picoMark_FUNCTION_BEGIN 217// Producer is `picoChip' 218.ascii 16#70# 16#69# 16#63# 16#6f# 16#43# 16#68# 16#69# 16#70# 16#00# 219.unalignedInitWord 0xcafe // ASM language 220.ascii 16#0# // Name. DwarfLib expects this to be present. 221 222.uleb128 0x2 ;# (DIE DW_TAG_subprogram) 223 224// FUNCTION NAME GOES HERE. Use `echo name | od -t x1' to get the hex. Each hex 225// digit is specified using the format 16#XX# 226.ascii 16#5f# 16#75# 16#64# 16#69# 16#76# 16#6d# 16#6f# 16#64# 16#68# 16#69# 16#34# 16#0# // Function name `_udivmodhi4' 227.unalignedInitWord _picoMark_FUNCTION_BEGIN // DW_AT_low_pc 228.unalignedInitWord _picoMark_FUNCTION_END // DW_AT_high_pc 229 230.initByte 0x0 // end of compile unit children. 231 232_picoMark_DEBUG_INFO_END= 233 234//============================================================================ 235// END OF DWARF 236//============================================================================ 237.section .endFile 238// End of picoChip ASM file 239