1/* libgcc routines for R8C/M16C/M32C 2 Copyright (C) 2005-2020 Free Software Foundation, Inc. 3 Contributed by Red Hat. 4 5 This file is part of GCC. 6 7 GCC is free software; you can redistribute it and/or modify it 8 under the terms of the GNU General Public License as published 9 by the Free Software Foundation; either version 3, or (at your 10 option) any later version. 11 12 GCC is distributed in the hope that it will be useful, but WITHOUT 13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 15 License for more details. 16 17 Under Section 7 of GPL version 3, you are granted additional 18 permissions described in the GCC Runtime Library Exception, version 19 3.1, as published by the Free Software Foundation. 20 21 You should have received a copy of the GNU General Public License and 22 a copy of the GCC Runtime Library Exception along with this program; 23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 24 <http://www.gnu.org/licenses/>. */ 25 26#if defined(__r8c_cpu__) || defined(__m16c_cpu__) 27#define A16 28#define A(n,w) n 29#define W w 30#else 31#define A24 32#define A(n,w) w 33#define W l 34#endif 35 36 37#ifdef L__m32c_memregs 38 39/* Warning: these memory locations are used as a register bank. They 40 *must* end up consecutive in any final executable, so you may *not* 41 use the otherwise obvious ".comm" directive to allocate space for 42 them. */ 43 44 .bss 45 .global mem0 46mem0: .space 1 47 .global mem1 48mem1: .space 1 49 .global mem2 50mem2: .space 1 51 .global mem3 52mem3: .space 1 53 .global mem4 54mem4: .space 1 55 .global mem5 56mem5: .space 1 57 .global mem6 58mem6: .space 1 59 .global mem7 60mem7: .space 1 61 .global mem8 62mem8: .space 1 63 .global mem9 64mem9: .space 1 65 .global mem10 66mem10: .space 1 67 .global mem11 68mem11: .space 1 69 .global mem12 70mem12: .space 1 71 .global mem13 72mem13: .space 1 73 .global mem14 74mem14: .space 1 75 .global mem15 76mem15: .space 1 77 78#endif 79 80#ifdef L__m32c_eh_return 81 .text 82 .global __m32c_eh_return 83__m32c_eh_return: 84 85 /* At this point, r0 has the stack adjustment, r1r3 has the 86 address to return to. The stack looks like this: 87 88 old_ra 89 old_fp 90 <- unwound sp 91 ... 92 fb 93 through 94 r0 95 <- sp 96 97 What we need to do is restore all the registers, update the 98 stack, and return to the right place. 99 */ 100 101 stc sp,a0 102 103 add.W A(#16,#24),a0 104 /* a0 points to the current stack, just above the register 105 save areas */ 106 107 mov.w a0,a1 108 exts.w r0 109 sub.W A(r0,r2r0),a1 110 sub.W A(#3,#4),a1 111 /* a1 points to the new stack. */ 112 113 /* This is for the "rts" below. */ 114 mov.w r1,[a1] 115#ifdef A16 116 mov.w r2,r1 117 mov.b r1l,2[a1] 118#else 119 mov.w r2,2[a1] 120#endif 121 122 /* This is for the "popc sp" below. */ 123 mov.W a1,[a0] 124 125 popm r0,r1,r2,r3,a0,a1,sb,fb 126 popc sp 127 rts 128#endif 129 130/* SImode arguments for SI foo(SI,SI) functions. */ 131#ifdef A16 132#define SAL 5[fb] 133#define SAH 7[fb] 134#define SBL 9[fb] 135#define SBH 11[fb] 136#else 137#define SAL 8[fb] 138#define SAH 10[fb] 139#define SBL 12[fb] 140#define SBH 14[fb] 141#endif 142 143#ifdef L__m32c_mulsi3 144 .text 145 .global ___mulsi3 146___mulsi3: 147 enter #0 148 push.w r2 149 mov.w SAL,r0 150 mulu.w SBL,r0 /* writes to r2r0 */ 151 mov.w r0,mem0 152 mov.w r2,mem2 153 mov.w SAL,r0 154 mulu.w SBH,r0 /* writes to r2r0 */ 155 add.w r0,mem2 156 mov.w SAH,r0 157 mulu.w SBL,r0 /* writes to r2r0 */ 158 add.w r0,mem2 159 pop.w r2 160 exitd 161#endif 162 163#ifdef L__m32c_cmpsi2 164 .text 165 .global ___cmpsi2 166___cmpsi2: 167 enter #0 168 cmp.w SBH,SAH 169 jgt cmpsi_gt 170 jlt cmpsi_lt 171 cmp.w SBL,SAL 172 jgt cmpsi_gt 173 jlt cmpsi_lt 174 mov.w #1,r0 175 exitd 176cmpsi_gt: 177 mov.w #2,r0 178 exitd 179cmpsi_lt: 180 mov.w #0,r0 181 exitd 182#endif 183 184#ifdef L__m32c_ucmpsi2 185 .text 186 .global ___ucmpsi2 187___ucmpsi2: 188 enter #0 189 cmp.w SBH,SAH 190 jgtu cmpsi_gt 191 jltu cmpsi_lt 192 cmp.w SBL,SAL 193 jgtu cmpsi_gt 194 jltu cmpsi_lt 195 mov.w #1,r0 196 exitd 197cmpsi_gt: 198 mov.w #2,r0 199 exitd 200cmpsi_lt: 201 mov.w #0,r0 202 exitd 203#endif 204 205#ifdef L__m32c_jsri16 206 .text 207#ifdef A16 208 .global m32c_jsri16 209m32c_jsri16: 210 add.w #-1, sp 211 212 /* Read the address (16 bits) and return address (24 bits) off 213 the stack. */ 214 mov.w 4[sp], r0 215 mov.w 1[sp], r3 216 mov.b 3[sp], a0 /* This zero-extends, so the high byte has 217 zero in it. */ 218 219 /* Write the return address, then new address, to the stack. */ 220 mov.w a0, 1[sp] /* Just to get the zero in 2[sp]. */ 221 mov.w r0, 0[sp] 222 mov.w r3, 3[sp] 223 mov.b a0, 5[sp] 224 225 /* This "returns" to the target address, leaving the pending 226 return address on the stack. */ 227 rts 228#endif 229 230#endif 231