They now mostly follow the same coding style as everything else.
Unified · Split
| @@ -29,40 +29,40 @@ · 28 unmodified lines | |||
| 29 | 29 | ||
| 30 | /* number of available registers */ | 30 | /* number of available registers */ |
| 31 | #ifdef TCC_ARM_VFP | 31 | #ifdef TCC_ARM_VFP |
| 32 | #define NB_REGS 13 | 32 | #define NB_REGS 13 |
| 33 | #else | 33 | #else |
| 34 | #define NB_REGS 9 | 34 | #define NB_REGS 9 |
| 35 | #endif | 35 | #endif |
| 36 | 36 | ||
| 37 | typedef int RegArgs; | 37 | typedef int RegArgs; |
| 38 | 38 | ||
| 39 | #ifndef TCC_ARM_VERSION | 39 | #ifndef TCC_ARM_VERSION |
| 40 | # define TCC_ARM_VERSION 5 | 40 | #define TCC_ARM_VERSION 5 |
| 41 | #endif | 41 | #endif |
| 42 | 42 | ||
| 43 | /* a register can belong to several classes. The classes must be | 43 | /* a register can belong to several classes. The classes must be |
| 44 | sorted from more general to more precise (see gv2() code which does | 44 | sorted from more general to more precise (see gv2() code which does |
| 45 | assumptions on it). */ | 45 | assumptions on it). */ |
| 46 | #define RC_INT 0x0001 /* generic integer register */ | 46 | #define RC_INT 0x0001 /* generic integer register */ |
| 47 | #define RC_FLOAT 0x0002 /* generic float register */ | 47 | #define RC_FLOAT 0x0002 /* generic float register */ |
| 48 | #define RC_R0 0x0004 | 48 | #define RC_R0 0x0004 |
| 49 | #define RC_R1 0x0008 | 49 | #define RC_R1 0x0008 |
| 50 | #define RC_R2 0x0010 | 50 | #define RC_R2 0x0010 |
| 51 | #define RC_R3 0x0020 | 51 | #define RC_R3 0x0020 |
| 52 | #define RC_R12 0x0040 | 52 | #define RC_R12 0x0040 |
| 53 | #define RC_F0 0x0080 | 53 | #define RC_F0 0x0080 |
| 54 | #define RC_F1 0x0100 | 54 | #define RC_F1 0x0100 |
| 55 | #define RC_F2 0x0200 | 55 | #define RC_F2 0x0200 |
| 56 | #define RC_F3 0x0400 | 56 | #define RC_F3 0x0400 |
| 57 | #ifdef TCC_ARM_VFP | 57 | #ifdef TCC_ARM_VFP |
| 58 | #define RC_F4 0x0800 | 58 | #define RC_F4 0x0800 |
| 59 | #define RC_F5 0x1000 | 59 | #define RC_F5 0x1000 |
| 60 | #define RC_F6 0x2000 | 60 | #define RC_F6 0x2000 |
| 61 | #define RC_F7 0x4000 | 61 | #define RC_F7 0x4000 |
| 62 | #endif | 62 | #endif |
| 63 | #define RC_IRET RC_R0 /* function return: integer register */ | 63 | #define RC_IRET RC_R0 /* function return: integer register */ |
| 64 | #define RC_LRET RC_R1 /* function return: second integer register */ | 64 | #define RC_LRET RC_R1 /* function return: second integer register */ |
| 65 | #define RC_FRET RC_F0 /* function return: float register */ | 65 | #define RC_FRET RC_F0 /* function return: float register */ |
| 66 | 66 | ||
| 67 | /* pretty names for the registers */ | 67 | /* pretty names for the registers */ |
| 68 | enum { | 68 | enum { |
| @@ -84,7 +84,7 @@ enum { · 15 unmodified lines | |||
| 84 | }; | 84 | }; |
| 85 | 85 | ||
| 86 | #ifdef TCC_ARM_VFP | 86 | #ifdef TCC_ARM_VFP |
| 87 | #define T2CPR(t) (((t) & VT_BTYPE) != VT_FLOAT ? 0x100 : 0) | 87 | #define T2CPR(t) (((t)&VT_BTYPE) != VT_FLOAT ? 0x100 : 0) |
| 88 | #endif | 88 | #endif |
| 89 | 89 | ||
| 90 | /* return registers for function */ | 90 | /* return registers for function */ |
| @@ -111,11 +111,11 @@ enum { · 20 unmodified lines | |||
| 111 | 111 | ||
| 112 | /* long double size and alignment, in bytes */ | 112 | /* long double size and alignment, in bytes */ |
| 113 | #ifdef TCC_ARM_VFP | 113 | #ifdef TCC_ARM_VFP |
| 114 | #define LDOUBLE_SIZE 8 | 114 | #define LDOUBLE_SIZE 8 |
| 115 | #endif | 115 | #endif |
| 116 | 116 | ||
| 117 | #ifndef LDOUBLE_SIZE | 117 | #ifndef LDOUBLE_SIZE |
| 118 | #define LDOUBLE_SIZE 8 | 118 | #define LDOUBLE_SIZE 8 |
| 119 | #endif | 119 | #endif |
| 120 | 120 | ||
| 121 | #ifdef TCC_ARM_EABI | 121 | #ifdef TCC_ARM_EABI |
| @@ -125,7 +125,7 @@ enum { · 3 unmodified lines | |||
| 125 | #endif | 125 | #endif |
| 126 | 126 | ||
| 127 | /* maximum alignment (for aligned attribute support) */ | 127 | /* maximum alignment (for aligned attribute support) */ |
| 128 | #define MAX_ALIGN 8 | 128 | #define MAX_ALIGN 8 |
| 129 | 129 | ||
| 130 | #define CHAR_IS_UNSIGNED | 130 | #define CHAR_IS_UNSIGNED |
| 131 | 131 | ||
| @@ -135,13 +135,13 @@ enum { · 3 unmodified lines | |||
| 135 | #define EM_TCC_TARGET EM_ARM | 135 | #define EM_TCC_TARGET EM_ARM |
| 136 | 136 | ||
| 137 | /* relocation type for 32 bit data relocation */ | 137 | /* relocation type for 32 bit data relocation */ |
| 138 | #define R_DATA_32 R_ARM_ABS32 | 138 | #define R_DATA_32 R_ARM_ABS32 |
| 139 | #define R_DATA_PTR R_ARM_ABS32 | 139 | #define R_DATA_PTR R_ARM_ABS32 |
| 140 | #define R_JMP_SLOT R_ARM_JUMP_SLOT | 140 | #define R_JMP_SLOT R_ARM_JUMP_SLOT |
| 141 | #define R_COPY R_ARM_COPY | 141 | #define R_COPY R_ARM_COPY |
| 142 | 142 | ||
| 143 | #define ELF_START_ADDR 0x00008000 | 143 | #define ELF_START_ADDR 0x00008000 |
| 144 | #define ELF_PAGE_SIZE 0x1000 | 144 | #define ELF_PAGE_SIZE 0x1000 |
| 145 | 145 | ||
| 146 | enum float_abi { | 146 | enum float_abi { |
| 147 | ARM_SOFTFP_FLOAT, | 147 | ARM_SOFTFP_FLOAT, |
| @@ -166,10 +166,10 @@ ST_DATA const int reg_classes[NB_REGS] = { · 18 unmodified lines | |||
| 166 | /* f2 */ RC_FLOAT | RC_F2, | 166 | /* f2 */ RC_FLOAT | RC_F2, |
| 167 | /* f3 */ RC_FLOAT | RC_F3, | 167 | /* f3 */ RC_FLOAT | RC_F3, |
| 168 | #ifdef TCC_ARM_VFP | 168 | #ifdef TCC_ARM_VFP |
| 169 | /* d4/s8 */ RC_FLOAT | RC_F4, | 169 | /* d4/s8 */ RC_FLOAT | RC_F4, |
| 170 | /* d5/s10 */ RC_FLOAT | RC_F5, | 170 | /* d5/s10 */ RC_FLOAT | RC_F5, |
| 171 | /* d6/s12 */ RC_FLOAT | RC_F6, | 171 | /* d6/s12 */ RC_FLOAT | RC_F6, |
| 172 | /* d7/s14 */ RC_FLOAT | RC_F7, | 172 | /* d7/s14 */ RC_FLOAT | RC_F7, |
| 173 | #endif | 173 | #endif |
| 174 | }; | 174 | }; |
| 175 | 175 | ||
| @@ -178,14 +178,16 @@ static int leaffunc; · 2 unmodified lines | |||
| 178 | 178 | ||
| 179 | #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP) | 179 | #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP) |
| 180 | static CType float_type, double_type, func_float_type, func_double_type; | 180 | static CType float_type, double_type, func_float_type, func_double_type; |
| 181 | ST_FUNC void arm_init(struct TCCState *s) | 181 | ST_FUNC void arm_init(struct TCCState* s) |
| 182 | { | 182 | { |
| 183 | float_type.t = VT_FLOAT; | 183 | float_type.t = VT_FLOAT; |
| 184 | double_type.t = VT_DOUBLE; | 184 | double_type.t = VT_DOUBLE; |
| 185 | func_float_type.t = VT_FUNC; | 185 | func_float_type.t = VT_FUNC; |
| 186 | func_float_type.ref = sym_push(SYM_FIELD, &float_type, FUNC_CDECL, FUNC_OLD); | 186 | func_float_type.ref = |
| 187 | sym_push(SYM_FIELD, &float_type, FUNC_CDECL, FUNC_OLD); | ||
| 187 | func_double_type.t = VT_FUNC; | 188 | func_double_type.t = VT_FUNC; |
| 188 | func_double_type.ref = sym_push(SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD); | 189 | func_double_type.ref = |
| 190 | sym_push(SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD); | ||
| 189 | 191 | ||
| 190 | float_abi = s->float_abi; | 192 | float_abi = s->float_abi; |
| 191 | #ifndef TCC_ARM_HARDFLOAT | 193 | #ifndef TCC_ARM_HARDFLOAT |
| @@ -196,31 +198,33 @@ ST_FUNC void arm_init(struct TCCState *s) · 4 unmodified lines | |||
| 196 | #define func_float_type func_old_type | 198 | #define func_float_type func_old_type |
| 197 | #define func_double_type func_old_type | 199 | #define func_double_type func_old_type |
| 198 | #define func_ldouble_type func_old_type | 200 | #define func_ldouble_type func_old_type |
| 199 | ST_FUNC void arm_init(struct TCCState *s) | 201 | ST_FUNC void arm_init(struct TCCState* s) |
| 200 | { | 202 | { |
| 201 | #if !defined (TCC_ARM_VFP) | 203 | #if !defined(TCC_ARM_VFP) |
| 202 | tcc_warning("Support for FPA is deprecated and will be removed in next" | 204 | tcc_warning("Support for FPA is deprecated and will be removed in next" |
| 203 | " release"); | 205 | " release"); |
| 204 | #endif | 206 | #endif |
| 205 | #if !defined (TCC_ARM_EABI) | 207 | #if !defined(TCC_ARM_EABI) |
| 206 | tcc_warning("Support for OABI is deprecated and will be removed in next" | 208 | tcc_warning("Support for OABI is deprecated and will be removed in next" |
| 207 | " release"); | 209 | " release"); |
| 208 | #endif | 210 | #endif |
| 209 | } | 211 | } |
| 210 | #endif | 212 | #endif |
| 211 | 213 | ||
| 212 | static int two2mask(int a,int b) { | 214 | static int two2mask(int a, int b) |
| 213 | return (reg_classes[a]|reg_classes[b])&~(RC_INT|RC_FLOAT); | 215 | { |
| 216 | return (reg_classes[a] | reg_classes[b]) & ~(RC_INT | RC_FLOAT); | ||
| 214 | } | 217 | } |
| 215 | 218 | ||
| 216 | static int regmask(int r) { | 219 | static int regmask(int r) |
| 217 | return reg_classes[r]&~(RC_INT|RC_FLOAT); | 220 | { |
| 221 | return reg_classes[r] & ~(RC_INT | RC_FLOAT); | ||
| 218 | } | 222 | } |
| 219 | 223 | ||
| 220 | /******************************************************/ | 224 | /******************************************************/ |
| 221 | 225 | ||
| 222 | #if defined(TCC_ARM_EABI) && !defined(CONFIG_TCC_ELFINTERP) | 226 | #if defined(TCC_ARM_EABI) && !defined(CONFIG_TCC_ELFINTERP) |
| 223 | char *default_elfinterp(struct TCCState *s) | 227 | char* default_elfinterp(struct TCCState* s) |
| 224 | { | 228 | { |
| 225 | if (s->float_abi == ARM_HARD_FLOAT) | 229 | if (s->float_abi == ARM_HARD_FLOAT) |
| 226 | return "/lib/ld-linux-armhf.so.3"; | 230 | return "/lib/ld-linux-armhf.so.3"; |
| @@ -231,551 +235,554 @@ char *default_elfinterp(struct TCCState *s) · 4 unmodified lines | |||
| 231 | 235 | ||
| 232 | void o(uint32_t i) | 236 | void o(uint32_t i) |
| 233 | { | 237 | { |
| 234 | /* this is a good place to start adding big-endian support*/ | 238 | /* this is a good place to start adding big-endian support*/ |
| 235 | int ind1; | 239 | int ind1; |
| 236 | 240 | ||
| 237 | ind1 = ind + 4; | 241 | ind1 = ind + 4; |
| 238 | if (!cur_text_section) | 242 | if (!cur_text_section) |
| 239 | tcc_error("compiler error! This happens f.ex. if the compiler\n" | 243 | tcc_error("compiler error! This happens f.ex. if the compiler\n" |
| 240 | "can't evaluate constant expressions outside of a function."); | 244 | "can't evaluate constant expressions outside of a function."); |
| 241 | if (ind1 > cur_text_section->data_allocated) | 245 | if (ind1 > cur_text_section->data_allocated) |
| 242 | section_realloc(cur_text_section, ind1); | 246 | section_realloc(cur_text_section, ind1); |
| 243 | cur_text_section->data[ind++] = i&255; | 247 | cur_text_section->data[ind++] = i & 255; |
| 244 | i>>=8; | 248 | i >>= 8; |
| 245 | cur_text_section->data[ind++] = i&255; | 249 | cur_text_section->data[ind++] = i & 255; |
| 246 | i>>=8; | 250 | i >>= 8; |
| 247 | cur_text_section->data[ind++] = i&255; | 251 | cur_text_section->data[ind++] = i & 255; |
| 248 | i>>=8; | 252 | i >>= 8; |
| 249 | cur_text_section->data[ind++] = i; | 253 | cur_text_section->data[ind++] = i; |
| 250 | } | 254 | } |
| 251 | 255 | ||
| 252 | static uint32_t stuff_const(uint32_t op, uint32_t c) | 256 | static uint32_t stuff_const(uint32_t op, uint32_t c) |
| 253 | { | 257 | { |
| 254 | int try_neg=0; | 258 | int try_neg = 0; |
| 255 | uint32_t nc = 0, negop = 0; | 259 | uint32_t nc = 0, negop = 0; |
| 256 | 260 | ||
| 257 | switch(op&0x1F00000) | 261 | switch (op & 0x1F00000) { |
| 258 | { | 262 | case 0x800000: // add |
| 259 | case 0x800000: //add | 263 | case 0x400000: // sub |
| 260 | case 0x400000: //sub | 264 | try_neg = 1; |
| 261 | try_neg=1; | 265 | negop = op ^ 0xC00000; |
| 262 | negop=op^0xC00000; | 266 | nc = -c; |
| 263 | nc=-c; | 267 | break; |
| 264 | break; | 268 | case 0x1A00000: // mov |
| 265 | case 0x1A00000: //mov | 269 | case 0x1E00000: // mvn |
| 266 | case 0x1E00000: //mvn | 270 | try_neg = 1; |
| 267 | try_neg=1; | 271 | negop = op ^ 0x400000; |
| 268 | negop=op^0x400000; | 272 | nc = ~c; |
| 269 | nc=~c; | 273 | break; |
| 270 | break; | 274 | case 0x200000: // xor |
| 271 | case 0x200000: //xor | 275 | if (c == ~0) |
| 272 | if(c==~0) | 276 | return (op & 0xF010F000) | ((op >> 16) & 0xF) | 0x1E00000; |
| 273 | return (op&0xF010F000)|((op>>16)&0xF)|0x1E00000; | 277 | break; |
| 274 | break; | 278 | case 0x0: // and |
| 275 | case 0x0: //and | 279 | if (c == ~0) |
| 276 | if(c==~0) | 280 | return (op & 0xF010F000) | ((op >> 16) & 0xF) | 0x1A00000; |
| 277 | return (op&0xF010F000)|((op>>16)&0xF)|0x1A00000; | 281 | case 0x1C00000: // bic |
| 278 | case 0x1C00000: //bic | 282 | try_neg = 1; |
| 279 | try_neg=1; | 283 | negop = op ^ 0x1C00000; |
| 280 | negop=op^0x1C00000; | 284 | nc = ~c; |
| 281 | nc=~c; | 285 | break; |
| 282 | break; | 286 | case 0x1800000: // orr |
| 283 | case 0x1800000: //orr | 287 | if (c == ~0) |
| 284 | if(c==~0) | 288 | return (op & 0xFFF0FFFF) | 0x1E00000; |
| 285 | return (op&0xFFF0FFFF)|0x1E00000; | 289 | break; |
| 286 | break; | ||
| 287 | } | ||
| 288 | do { | ||
| 289 | uint32_t m; | ||
| 290 | int i; | ||
| 291 | if(c<256) /* catch undefined <<32 */ | ||
| 292 | return op|c; | ||
| 293 | for(i=2;i<32;i+=2) { | ||
| 294 | m=(0xff>>i)|(0xff<<(32-i)); | ||
| 295 | if(!(c&~m)) | ||
| 296 | return op|(i<<7)|(c<<i)|(c>>(32-i)); | ||
| 297 | } | 290 | } |
| 298 | op=negop; | 291 | do { |
| 299 | c=nc; | 292 | uint32_t m; |
| 300 | } while(try_neg--); | 293 | int i; |
| 301 | return 0; | 294 | if (c < 256) /* catch undefined <<32 */ |
| 295 | return op | c; | ||
| 296 | for (i = 2; i < 32; i += 2) { | ||
| 297 | m = (0xff >> i) | (0xff << (32 - i)); | ||
| 298 | if (!(c & ~m)) | ||
| 299 | return op | (i << 7) | (c << i) | (c >> (32 - i)); | ||
| 300 | } | ||
| 301 | op = negop; | ||
| 302 | c = nc; | ||
| 303 | } while (try_neg--); | ||
| 304 | return 0; | ||
| 302 | } | 305 | } |
| 303 | 306 | ||
| 304 | 307 | // only add,sub | |
| 305 | //only add,sub | 308 | void stuff_const_harder(uint32_t op, uint32_t v) |
| 306 | void stuff_const_harder(uint32_t op, uint32_t v) { | 309 | { |
| 307 | uint32_t x; | 310 | uint32_t x; |
| 308 | x=stuff_const(op,v); | 311 | x = stuff_const(op, v); |
| 309 | if(x) | 312 | if (x) |
| 310 | o(x); | 313 | o(x); |
| 311 | else { | 314 | else { |
| 312 | uint32_t a[16], nv, no, o2, n2; | 315 | uint32_t a[16], nv, no, o2, n2; |
| 313 | int i,j,k; | 316 | int i, j, k; |
| 314 | a[0]=0xff; | 317 | a[0] = 0xff; |
| 315 | o2=(op&0xfff0ffff)|((op&0xf000)<<4);; | 318 | o2 = (op & 0xfff0ffff) | ((op & 0xf000) << 4); |
| 316 | for(i=1;i<16;i++) | 319 | ; |
| 317 | a[i]=(a[i-1]>>2)|(a[i-1]<<30); | 320 | for (i = 1; i < 16; i++) |
| 318 | for(i=0;i<12;i++) | 321 | a[i] = (a[i - 1] >> 2) | (a[i - 1] << 30); |
| 319 | for(j=i<4?i+12:15;j>=i+4;j--) | 322 | for (i = 0; i < 12; i++) |
| 320 | if((v&(a[i]|a[j]))==v) { | 323 | for (j = i < 4 ? i + 12 : 15; j >= i + 4; j--) |
| 321 | o(stuff_const(op,v&a[i])); | 324 | if ((v & (a[i] | a[j])) == v) { |
| 322 | o(stuff_const(o2,v&a[j])); | 325 | o(stuff_const(op, v & a[i])); |
| 323 | return; | 326 | o(stuff_const(o2, v & a[j])); |
| 324 | } | 327 | return; |
| 325 | no=op^0xC00000; | 328 | } |
| 326 | n2=o2^0xC00000; | 329 | no = op ^ 0xC00000; |
| 327 | nv=-v; | 330 | n2 = o2 ^ 0xC00000; |
| 328 | for(i=0;i<12;i++) | 331 | nv = -v; |
| 329 | for(j=i<4?i+12:15;j>=i+4;j--) | 332 | for (i = 0; i < 12; i++) |
| 330 | if((nv&(a[i]|a[j]))==nv) { | 333 | for (j = i < 4 ? i + 12 : 15; j >= i + 4; j--) |
| 331 | o(stuff_const(no,nv&a[i])); | 334 | if ((nv & (a[i] | a[j])) == nv) { |
| 332 | o(stuff_const(n2,nv&a[j])); | 335 | o(stuff_const(no, nv & a[i])); |
| 333 | return; | 336 | o(stuff_const(n2, nv & a[j])); |
| 334 | } | 337 | return; |
| 335 | for(i=0;i<8;i++) | 338 | } |
| 336 | for(j=i+4;j<12;j++) | 339 | for (i = 0; i < 8; i++) |
| 337 | for(k=i<4?i+12:15;k>=j+4;k--) | 340 | for (j = i + 4; j < 12; j++) |
| 338 | if((v&(a[i]|a[j]|a[k]))==v) { | 341 | for (k = i < 4 ? i + 12 : 15; k >= j + 4; k--) |
| 339 | o(stuff_const(op,v&a[i])); | 342 | if ((v & (a[i] | a[j] | a[k])) == v) { |
| 340 | o(stuff_const(o2,v&a[j])); | 343 | o(stuff_const(op, v & a[i])); |
| 341 | o(stuff_const(o2,v&a[k])); | 344 | o(stuff_const(o2, v & a[j])); |
| 342 | return; | 345 | o(stuff_const(o2, v & a[k])); |
| 343 | } | 346 | return; |
| 344 | no=op^0xC00000; | 347 | } |
| 345 | nv=-v; | 348 | no = op ^ 0xC00000; |
| 346 | for(i=0;i<8;i++) | 349 | nv = -v; |
| 347 | for(j=i+4;j<12;j++) | 350 | for (i = 0; i < 8; i++) |
| 348 | for(k=i<4?i+12:15;k>=j+4;k--) | 351 | for (j = i + 4; j < 12; j++) |
| 349 | if((nv&(a[i]|a[j]|a[k]))==nv) { | 352 | for (k = i < 4 ? i + 12 : 15; k >= j + 4; k--) |
| 350 | o(stuff_const(no,nv&a[i])); | 353 | if ((nv & (a[i] | a[j] | a[k])) == nv) { |
| 351 | o(stuff_const(n2,nv&a[j])); | 354 | o(stuff_const(no, nv & a[i])); |
| 352 | o(stuff_const(n2,nv&a[k])); | 355 | o(stuff_const(n2, nv & a[j])); |
| 353 | return; | 356 | o(stuff_const(n2, nv & a[k])); |
| 354 | } | 357 | return; |
| 355 | o(stuff_const(op,v&a[0])); | 358 | } |
| 356 | o(stuff_const(o2,v&a[4])); | 359 | o(stuff_const(op, v & a[0])); |
| 357 | o(stuff_const(o2,v&a[8])); | 360 | o(stuff_const(o2, v & a[4])); |
| 358 | o(stuff_const(o2,v&a[12])); | 361 | o(stuff_const(o2, v & a[8])); |
| 359 | } | 362 | o(stuff_const(o2, v & a[12])); |
| 363 | } | ||
| 360 | } | 364 | } |
| 361 | 365 | ||
| 362 | ST_FUNC uint32_t encbranch(int pos, int addr, int fail) | 366 | ST_FUNC uint32_t encbranch(int pos, int addr, int fail) |
| 363 | { | 367 | { |
| 364 | addr-=pos+8; | 368 | addr -= pos + 8; |
| 365 | addr/=4; | 369 | addr /= 4; |
| 366 | if(addr>=0x1000000 || addr<-0x1000000) { | 370 | if (addr >= 0x1000000 || addr < -0x1000000) { |
| 367 | if(fail) | 371 | if (fail) |
| 368 | tcc_error("FIXME: function bigger than 32MB"); | 372 | tcc_error("FIXME: function bigger than 32MB"); |
| 369 | return 0; | 373 | return 0; |
| 370 | } | 374 | } |
| 371 | return 0x0A000000|(addr&0xffffff); | 375 | return 0x0A000000 | (addr & 0xffffff); |
| 372 | } | 376 | } |
| 373 | 377 | ||
| 374 | int decbranch(int pos) | 378 | int decbranch(int pos) |
| 375 | { | 379 | { |
| 376 | int x; | 380 | int x; |
| 377 | x=*(uint32_t *)(cur_text_section->data + pos); | 381 | x = *(uint32_t*)(cur_text_section->data + pos); |
| 378 | x&=0x00ffffff; | 382 | x &= 0x00ffffff; |
| 379 | if(x&0x800000) | 383 | if (x & 0x800000) |
| 380 | x-=0x1000000; | 384 | x -= 0x1000000; |
| 381 | return x*4+pos+8; | 385 | return x * 4 + pos + 8; |
| 382 | } | 386 | } |
| 383 | 387 | ||
| 384 | /* output a symbol and patch all calls to it */ | 388 | /* output a symbol and patch all calls to it */ |
| 385 | void gsym_addr(int t, int a) | 389 | void gsym_addr(int t, int a) |
| 386 | { | 390 | { |
| 387 | uint32_t *x; | 391 | uint32_t* x; |
| 388 | int lt; | 392 | int lt; |
| 389 | while(t) { | 393 | while (t) { |
| 390 | x=(uint32_t *)(cur_text_section->data + t); | 394 | x = (uint32_t*)(cur_text_section->data + t); |
| 391 | t=decbranch(lt=t); | 395 | t = decbranch(lt = t); |
| 392 | if(a==lt+4) | 396 | if (a == lt + 4) |
| 393 | *x=0xE1A00000; // nop | 397 | *x = 0xE1A00000; // nop |
| 394 | else { | 398 | else { |
| 395 | *x &= 0xff000000; | 399 | *x &= 0xff000000; |
| 396 | *x |= encbranch(lt,a,1); | 400 | *x |= encbranch(lt, a, 1); |
| 401 | } | ||
| 397 | } | 402 | } |
| 398 | } | ||
| 399 | } | 403 | } |
| 400 | 404 | ||
| 401 | void gsym(int t) | 405 | void gsym(int t) |
| 402 | { | 406 | { |
| 403 | gsym_addr(t, ind); | 407 | gsym_addr(t, ind); |
| 404 | } | 408 | } |
| 405 | 409 | ||
| 406 | #ifdef TCC_ARM_VFP | 410 | #ifdef TCC_ARM_VFP |
| 407 | static uint32_t vfpr(int r) | 411 | static uint32_t vfpr(int r) |
| 408 | { | 412 | { |
| 409 | if(r<TREG_F0 || r>TREG_F7) | 413 | if (r < TREG_F0 || r > TREG_F7) |
| 410 | tcc_error("compiler error! register %i is no vfp register",r); | 414 | tcc_error("compiler error! register %i is no vfp register", r); |
| 411 | return r-5; | 415 | return r - 5; |
| 412 | } | 416 | } |
| 413 | #else | 417 | #else |
| 414 | static uint32_t fpr(int r) | 418 | static uint32_t fpr(int r) |
| 415 | { | 419 | { |
| 416 | if(r<TREG_F0 || r>TREG_F3) | 420 | if (r < TREG_F0 || r > TREG_F3) |
| 417 | tcc_error("compiler error! register %i is no fpa register",r); | 421 | tcc_error("compiler error! register %i is no fpa register", r); |
| 418 | return r-5; | 422 | return r - 5; |
| 419 | } | 423 | } |
| 420 | #endif | 424 | #endif |
| 421 | 425 | ||
| 422 | static uint32_t intr(int r) | 426 | static uint32_t intr(int r) |
| 423 | { | 427 | { |
| 424 | if(r==4) | 428 | if (r == 4) |
| 425 | return 12; | 429 | return 12; |
| 426 | if((r<0 || r>4) && r!=14) | 430 | if ((r < 0 || r > 4) && r != 14) |
| 427 | tcc_error("compiler error! register %i is no int register",r); | 431 | tcc_error("compiler error! register %i is no int register", r); |
| 428 | return r; | 432 | return r; |
| 429 | } | 433 | } |
| 430 | 434 | ||
| 431 | static void calcaddr(uint32_t *base, int *off, int *sgn, int maxoff, unsigned shift) | 435 | static void calcaddr(uint32_t* base, int* off, int* sgn, int maxoff, |
| 436 | unsigned shift) | ||
| 432 | { | 437 | { |
| 433 | if(*off>maxoff || *off&((1<<shift)-1)) { | 438 | if (*off > maxoff || *off & ((1 << shift) - 1)) { |
| 434 | uint32_t x, y; | 439 | uint32_t x, y; |
| 435 | x=0xE280E000; | 440 | x = 0xE280E000; |
| 436 | if(*sgn) | 441 | if (*sgn) |
| 437 | x=0xE240E000; | 442 | x = 0xE240E000; |
| 438 | x|=(*base)<<16; | 443 | x |= (*base) << 16; |
| 439 | *base=14; // lr | 444 | *base = 14; // lr |
| 440 | y=stuff_const(x,*off&~maxoff); | 445 | y = stuff_const(x, *off & ~maxoff); |
| 441 | if(y) { | 446 | if (y) { |
| 442 | o(y); | 447 | o(y); |
| 443 | *off&=maxoff; | 448 | *off &= maxoff; |
| 444 | return; | 449 | return; |
| 445 | } | 450 | } |
| 446 | y=stuff_const(x,(*off+maxoff)&~maxoff); | 451 | y = stuff_const(x, (*off + maxoff) & ~maxoff); |
| 447 | if(y) { | 452 | if (y) { |
| 448 | o(y); | 453 | o(y); |
| 449 | *sgn=!*sgn; | 454 | *sgn = !*sgn; |
| 450 | *off=((*off+maxoff)&~maxoff)-*off; | 455 | *off = ((*off + maxoff) & ~maxoff) - *off; |
| 451 | return; | 456 | return; |
| 457 | } | ||
| 458 | stuff_const_harder(x, *off & ~maxoff); | ||
| 459 | *off &= maxoff; | ||
| 452 | } | 460 | } |
| 453 | stuff_const_harder(x,*off&~maxoff); | ||
| 454 | *off&=maxoff; | ||
| 455 | } | ||
| 456 | } | 461 | } |
| 457 | 462 | ||
| 458 | static uint32_t mapcc(int cc) | 463 | static uint32_t mapcc(int cc) |
| 459 | { | 464 | { |
| 460 | switch(cc) | 465 | switch (cc) { |
| 461 | { | ||
| 462 | case TOK_ULT: | 466 | case TOK_ULT: |
| 463 | return 0x30000000; /* CC/LO */ | 467 | return 0x30000000; /* CC/LO */ |
| 464 | case TOK_UGE: | 468 | case TOK_UGE: |
| 465 | return 0x20000000; /* CS/HS */ | 469 | return 0x20000000; /* CS/HS */ |
| 466 | case TOK_EQ: | 470 | case TOK_EQ: |
| 467 | return 0x00000000; /* EQ */ | 471 | return 0x00000000; /* EQ */ |
| 468 | case TOK_NE: | 472 | case TOK_NE: |
| 469 | return 0x10000000; /* NE */ | 473 | return 0x10000000; /* NE */ |
| 470 | case TOK_ULE: | 474 | case TOK_ULE: |
| 471 | return 0x90000000; /* LS */ | 475 | return 0x90000000; /* LS */ |
| 472 | case TOK_UGT: | 476 | case TOK_UGT: |
| 473 | return 0x80000000; /* HI */ | 477 | return 0x80000000; /* HI */ |
| 474 | case TOK_Nset: | 478 | case TOK_Nset: |
| 475 | return 0x40000000; /* MI */ | 479 | return 0x40000000; /* MI */ |
| 476 | case TOK_Nclear: | 480 | case TOK_Nclear: |
| 477 | return 0x50000000; /* PL */ | 481 | return 0x50000000; /* PL */ |
| 478 | case TOK_LT: | 482 | case TOK_LT: |
| 479 | return 0xB0000000; /* LT */ | 483 | return 0xB0000000; /* LT */ |
| 480 | case TOK_GE: | 484 | case TOK_GE: |
| 481 | return 0xA0000000; /* GE */ | 485 | return 0xA0000000; /* GE */ |
| 482 | case TOK_LE: | 486 | case TOK_LE: |
| 483 | return 0xD0000000; /* LE */ | 487 | return 0xD0000000; /* LE */ |
| 484 | case TOK_GT: | 488 | case TOK_GT: |
| 485 | return 0xC0000000; /* GT */ | 489 | return 0xC0000000; /* GT */ |
| 486 | } | 490 | } |
| 487 | tcc_error("unexpected condition code"); | 491 | tcc_error("unexpected condition code"); |
| 488 | return 0xE0000000; /* AL */ | 492 | return 0xE0000000; /* AL */ |
| 489 | } | 493 | } |
| 490 | 494 | ||
| 491 | static int negcc(int cc) | 495 | static int negcc(int cc) |
| 492 | { | 496 | { |
| 493 | switch(cc) | 497 | switch (cc) { |
| 494 | { | ||
| 495 | case TOK_ULT: | 498 | case TOK_ULT: |
| 496 | return TOK_UGE; | 499 | return TOK_UGE; |
| 497 | case TOK_UGE: | 500 | case TOK_UGE: |
| 498 | return TOK_ULT; | 501 | return TOK_ULT; |
| 499 | case TOK_EQ: | 502 | case TOK_EQ: |
| 500 | return TOK_NE; | 503 | return TOK_NE; |
| 501 | case TOK_NE: | 504 | case TOK_NE: |
| 502 | return TOK_EQ; | 505 | return TOK_EQ; |
| 503 | case TOK_ULE: | 506 | case TOK_ULE: |
| 504 | return TOK_UGT; | 507 | return TOK_UGT; |
| 505 | case TOK_UGT: | 508 | case TOK_UGT: |
| 506 | return TOK_ULE; | 509 | return TOK_ULE; |
| 507 | case TOK_Nset: | 510 | case TOK_Nset: |
| 508 | return TOK_Nclear; | 511 | return TOK_Nclear; |
| 509 | case TOK_Nclear: | 512 | case TOK_Nclear: |
| 510 | return TOK_Nset; | 513 | return TOK_Nset; |
| 511 | case TOK_LT: | 514 | case TOK_LT: |
| 512 | return TOK_GE; | 515 | return TOK_GE; |
| 513 | case TOK_GE: | 516 | case TOK_GE: |
| 514 | return TOK_LT; | 517 | return TOK_LT; |
| 515 | case TOK_LE: | 518 | case TOK_LE: |
| 516 | return TOK_GT; | 519 | return TOK_GT; |
| 517 | case TOK_GT: | 520 | case TOK_GT: |
| 518 | return TOK_LE; | 521 | return TOK_LE; |
| 519 | } | 522 | } |
| 520 | tcc_error("unexpected condition code"); | 523 | tcc_error("unexpected condition code"); |
| 521 | return TOK_NE; | 524 | return TOK_NE; |
| 522 | } | 525 | } |
| 523 | 526 | ||
| 524 | /* load 'r' from value 'sv' */ | 527 | /* load 'r' from value 'sv' */ |
| 525 | void load(int r, SValue *sv) | 528 | void load(int r, SValue* sv) |
| 526 | { | 529 | { |
| 527 | int v, ft, fc, fr, sign; | 530 | int v, ft, fc, fr, sign; |
| 528 | uint32_t op; | 531 | uint32_t op; |
| 529 | SValue v1; | 532 | SValue v1; |
| 530 | 533 | ||
| 531 | fr = sv->r; | 534 | fr = sv->r; |
| 532 | ft = sv->type.t; | 535 | ft = sv->type.t; |
| 533 | fc = sv->c.ul; | 536 | fc = sv->c.ul; |
| 534 | 537 | ||
| 535 | if(fc>=0) | 538 | if (fc >= 0) |
| 536 | sign=0; | 539 | sign = 0; |
| 537 | else { | 540 | else { |
| 538 | sign=1; | 541 | sign = 1; |
| 539 | fc=-fc; | 542 | fc = -fc; |
| 540 | } | ||
| 541 | |||
| 542 | v = fr & VT_VALMASK; | ||
| 543 | if (fr & VT_LVAL) { | ||
| 544 | uint32_t base = 0xB; // fp | ||
| 545 | if(v == VT_LLOCAL) { | ||
| 546 | v1.type.t = VT_PTR; | ||
| 547 | v1.r = VT_LOCAL | VT_LVAL; | ||
| 548 | v1.c.ul = sv->c.ul; | ||
| 549 | load(base=14 /* lr */, &v1); | ||
| 550 | fc=sign=0; | ||
| 551 | v=VT_LOCAL; | ||
| 552 | } else if(v == VT_CONST) { | ||
| 553 | v1.type.t = VT_PTR; | ||
| 554 | v1.r = fr&~VT_LVAL; | ||
| 555 | v1.c.ul = sv->c.ul; | ||
| 556 | v1.sym=sv->sym; | ||
| 557 | load(base=14, &v1); | ||
| 558 | fc=sign=0; | ||
| 559 | v=VT_LOCAL; | ||
| 560 | } else if(v < VT_CONST) { | ||
| 561 | base=intr(v); | ||
| 562 | fc=sign=0; | ||
| 563 | v=VT_LOCAL; | ||
| 564 | } | 543 | } |
| 565 | if(v == VT_LOCAL) { | 544 | |
| 566 | if(is_float(ft)) { | 545 | v = fr & VT_VALMASK; |
| 567 | calcaddr(&base,&fc,&sign,1020,2); | 546 | if (fr & VT_LVAL) { |
| 547 | uint32_t base = 0xB; // fp | ||
| 548 | if (v == VT_LLOCAL) { | ||
| 549 | v1.type.t = VT_PTR; | ||
| 550 | v1.r = VT_LOCAL | VT_LVAL; | ||
| 551 | v1.c.ul = sv->c.ul; | ||
| 552 | load(base = 14 /* lr */, &v1); | ||
| 553 | fc = sign = 0; | ||
| 554 | v = VT_LOCAL; | ||
| 555 | } else if (v == VT_CONST) { | ||
| 556 | v1.type.t = VT_PTR; | ||
| 557 | v1.r = fr & ~VT_LVAL; | ||
| 558 | v1.c.ul = sv->c.ul; | ||
| 559 | v1.sym = sv->sym; | ||
| 560 | load(base = 14, &v1); | ||
| 561 | fc = sign = 0; | ||
| 562 | v = VT_LOCAL; | ||
| 563 | } else if (v < VT_CONST) { | ||
| 564 | base = intr(v); | ||
| 565 | fc = sign = 0; | ||
| 566 | v = VT_LOCAL; | ||
| 567 | } | ||
| 568 | if (v == VT_LOCAL) { | ||
| 569 | if (is_float(ft)) { | ||
| 570 | calcaddr(&base, &fc, &sign, 1020, 2); | ||
| 568 | #ifdef TCC_ARM_VFP | 571 | #ifdef TCC_ARM_VFP |
| 569 | op=0xED100A00; /* flds */ | 572 | op = 0xED100A00; /* flds */ |
| 570 | if(!sign) | 573 | if (!sign) |
| 571 | op|=0x800000; | 574 | op |= 0x800000; |
| 572 | if ((ft & VT_BTYPE) != VT_FLOAT) | 575 | if ((ft & VT_BTYPE) != VT_FLOAT) |
| 573 | op|=0x100; /* flds -> fldd */ | 576 | op |= 0x100; /* flds -> fldd */ |
| 574 | o(op|(vfpr(r)<<12)|(fc>>2)|(base<<16)); | 577 | o(op | (vfpr(r) << 12) | (fc >> 2) | (base << 16)); |
| 575 | #else | 578 | #else |
| 576 | op=0xED100100; | 579 | op = 0xED100100; |
| 577 | if(!sign) | 580 | if (!sign) |
| 578 | op|=0x800000; | 581 | op |= 0x800000; |
| 579 | #if LDOUBLE_SIZE == 8 | 582 | #if LDOUBLE_SIZE == 8 |
| 580 | if ((ft & VT_BTYPE) != VT_FLOAT) | 583 | if ((ft & VT_BTYPE) != VT_FLOAT) |
| 581 | op|=0x8000; | 584 | op |= 0x8000; |
| 582 | #else | 585 | #else |
| 583 | if ((ft & VT_BTYPE) == VT_DOUBLE) | 586 | if ((ft & VT_BTYPE) == VT_DOUBLE) |
| 584 | op|=0x8000; | 587 | op |= 0x8000; |
| 585 | else if ((ft & VT_BTYPE) == VT_LDOUBLE) | 588 | else if ((ft & VT_BTYPE) == VT_LDOUBLE) |
| 586 | op|=0x400000; | 589 | op |= 0x400000; |
| 587 | #endif | 590 | #endif |
| 588 | o(op|(fpr(r)<<12)|(fc>>2)|(base<<16)); | 591 | o(op | (fpr(r) << 12) | (fc >> 2) | (base << 16)); |
| 589 | #endif | 592 | #endif |
| 590 | } else if((ft & (VT_BTYPE|VT_UNSIGNED)) == VT_BYTE | 593 | } else if ((ft & (VT_BTYPE | VT_UNSIGNED)) == VT_BYTE || |
| 591 | || (ft & VT_BTYPE) == VT_SHORT) { | 594 | (ft & VT_BTYPE) == VT_SHORT) { |
| 592 | calcaddr(&base,&fc,&sign,255,0); | 595 | calcaddr(&base, &fc, &sign, 255, 0); |
| 593 | op=0xE1500090; | 596 | op = 0xE1500090; |
| 594 | if ((ft & VT_BTYPE) == VT_SHORT) | 597 | if ((ft & VT_BTYPE) == VT_SHORT) |
| 595 | op|=0x20; | 598 | op |= 0x20; |
| 596 | if ((ft & VT_UNSIGNED) == 0) | 599 | if ((ft & VT_UNSIGNED) == 0) |
| 597 | op|=0x40; | 600 | op |= 0x40; |
| 598 | if(!sign) | 601 | if (!sign) |
| 599 | op|=0x800000; | 602 | op |= 0x800000; |
| 600 | o(op|(intr(r)<<12)|(base<<16)|((fc&0xf0)<<4)|(fc&0xf)); | 603 | o(op | (intr(r) << 12) | (base << 16) | ((fc & 0xf0) << 4) | |
| 601 | } else { | 604 | (fc & 0xf)); |
| 602 | calcaddr(&base,&fc,&sign,4095,0); | 605 | } else { |
| 603 | op=0xE5100000; | 606 | calcaddr(&base, &fc, &sign, 4095, 0); |
| 604 | if(!sign) | 607 | op = 0xE5100000; |
| 605 | op|=0x800000; | 608 | if (!sign) |
| 606 | if ((ft & VT_BTYPE) == VT_BYTE || (ft & VT_BTYPE) == VT_BOOL) | 609 | op |= 0x800000; |
| 607 | op|=0x400000; | 610 | if ((ft & VT_BTYPE) == VT_BYTE || (ft & VT_BTYPE) == VT_BOOL) |
| 608 | o(op|(intr(r)<<12)|fc|(base<<16)); | 611 | op |= 0x400000; |
| 609 | } | 612 | o(op | (intr(r) << 12) | fc | (base << 16)); |
| 610 | return; | 613 | } |
| 611 | } | 614 | return; |
| 612 | } else { | 615 | } |
| 613 | if (v == VT_CONST) { | 616 | } else { |
| 614 | op=stuff_const(0xE3A00000|(intr(r)<<12),sv->c.ul); | 617 | if (v == VT_CONST) { |
| 615 | if (fr & VT_SYM || !op) { | 618 | op = stuff_const(0xE3A00000 | (intr(r) << 12), sv->c.ul); |
| 616 | o(0xE59F0000|(intr(r)<<12)); | 619 | if (fr & VT_SYM || !op) { |
| 617 | o(0xEA000000); | 620 | o(0xE59F0000 | (intr(r) << 12)); |
| 618 | if(fr & VT_SYM) | 621 | o(0xEA000000); |
| 619 | greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32); | 622 | if (fr & VT_SYM) |
| 620 | o(sv->c.ul); | 623 | greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32); |
| 621 | } else | 624 | o(sv->c.ul); |
| 622 | o(op); | 625 | } else |
| 623 | return; | 626 | o(op); |
| 624 | } else if (v == VT_LOCAL) { | 627 | return; |
| 625 | op=stuff_const(0xE28B0000|(intr(r)<<12),sv->c.ul); | 628 | } else if (v == VT_LOCAL) { |
| 626 | if (fr & VT_SYM || !op) { | 629 | op = stuff_const(0xE28B0000 | (intr(r) << 12), sv->c.ul); |
| 627 | o(0xE59F0000|(intr(r)<<12)); | 630 | if (fr & VT_SYM || !op) { |
| 628 | o(0xEA000000); | 631 | o(0xE59F0000 | (intr(r) << 12)); |
| 629 | if(fr & VT_SYM) // needed ? | 632 | o(0xEA000000); |
| 630 | greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32); | 633 | if (fr & VT_SYM) // needed ? |
| 631 | o(sv->c.ul); | 634 | greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32); |
| 632 | o(0xE08B0000|(intr(r)<<12)|intr(r)); | 635 | o(sv->c.ul); |
| 633 | } else | 636 | o(0xE08B0000 | (intr(r) << 12) | intr(r)); |
| 634 | o(op); | 637 | } else |
| 635 | return; | 638 | o(op); |
| 636 | } else if(v == VT_CMP) { | 639 | return; |
| 637 | o(mapcc(sv->c.ul)|0x3A00001|(intr(r)<<12)); | 640 | } else if (v == VT_CMP) { |
| 638 | o(mapcc(negcc(sv->c.ul))|0x3A00000|(intr(r)<<12)); | 641 | o(mapcc(sv->c.ul) | 0x3A00001 | (intr(r) << 12)); |
| 639 | return; | 642 | o(mapcc(negcc(sv->c.ul)) | 0x3A00000 | (intr(r) << 12)); |
| 640 | } else if (v == VT_JMP || v == VT_JMPI) { | 643 | return; |
| 641 | int t; | 644 | } else if (v == VT_JMP || v == VT_JMPI) { |
| 642 | t = v & 1; | 645 | int t; |
| 643 | o(0xE3A00000|(intr(r)<<12)|t); | 646 | t = v & 1; |
| 644 | o(0xEA000000); | 647 | o(0xE3A00000 | (intr(r) << 12) | t); |
| 645 | gsym(sv->c.ul); | 648 | o(0xEA000000); |
| 646 | o(0xE3A00000|(intr(r)<<12)|(t^1)); | 649 | gsym(sv->c.ul); |
| 647 | return; | 650 | o(0xE3A00000 | (intr(r) << 12) | (t ^ 1)); |
| 648 | } else if (v < VT_CONST) { | 651 | return; |
| 649 | if(is_float(ft)) | 652 | } else if (v < VT_CONST) { |
| 653 | if (is_float(ft)) | ||
| 650 | #ifdef TCC_ARM_VFP | 654 | #ifdef TCC_ARM_VFP |
| 651 | o(0xEEB00A40|(vfpr(r)<<12)|vfpr(v)|T2CPR(ft)); /* fcpyX */ | 655 | o(0xEEB00A40 | (vfpr(r) << 12) | vfpr(v) | |
| 656 | T2CPR(ft)); /* fcpyX */ | ||
| 652 | #else | 657 | #else |
| 653 | o(0xEE008180|(fpr(r)<<12)|fpr(v)); | 658 | o(0xEE008180 | (fpr(r) << 12) | fpr(v)); |
| 654 | #endif | 659 | #endif |
| 655 | else | 660 | else |
| 656 | o(0xE1A00000|(intr(r)<<12)|intr(v)); | 661 | o(0xE1A00000 | (intr(r) << 12) | intr(v)); |
| 657 | return; | 662 | return; |
| 663 | } | ||
| 658 | } | 664 | } |
| 659 | } | 665 | tcc_error("load unimplemented!"); |
| 660 | tcc_error("load unimplemented!"); | ||
| 661 | } | 666 | } |
| 662 | 667 | ||
| 663 | /* store register 'r' in lvalue 'v' */ | 668 | /* store register 'r' in lvalue 'v' */ |
| 664 | void store(int r, SValue *sv) | 669 | void store(int r, SValue* sv) |
| 665 | { | 670 | { |
| 666 | SValue v1; | 671 | SValue v1; |
| 667 | int v, ft, fc, fr, sign; | 672 | int v, ft, fc, fr, sign; |
| 668 | uint32_t op; | 673 | uint32_t op; |
| 669 | 674 | ||
| 670 | fr = sv->r; | 675 | fr = sv->r; |
| 671 | ft = sv->type.t; | 676 | ft = sv->type.t; |
| 672 | fc = sv->c.ul; | 677 | fc = sv->c.ul; |
| 673 | 678 | ||
| 674 | if(fc>=0) | 679 | if (fc >= 0) |
| 675 | sign=0; | 680 | sign = 0; |
| 676 | else { | 681 | else { |
| 677 | sign=1; | 682 | sign = 1; |
| 678 | fc=-fc; | 683 | fc = -fc; |
| 679 | } | ||
| 680 | |||
| 681 | v = fr & VT_VALMASK; | ||
| 682 | if (fr & VT_LVAL || fr == VT_LOCAL) { | ||
| 683 | uint32_t base = 0xb; | ||
| 684 | if(v < VT_CONST) { | ||
| 685 | base=intr(v); | ||
| 686 | v=VT_LOCAL; | ||
| 687 | fc=sign=0; | ||
| 688 | } else if(v == VT_CONST) { | ||
| 689 | v1.type.t = ft; | ||
| 690 | v1.r = fr&~VT_LVAL; | ||
| 691 | v1.c.ul = sv->c.ul; | ||
| 692 | v1.sym=sv->sym; | ||
| 693 | load(base=14, &v1); | ||
| 694 | fc=sign=0; | ||
| 695 | v=VT_LOCAL; | ||
| 696 | } | 684 | } |
| 697 | if(v == VT_LOCAL) { | 685 | |
| 698 | if(is_float(ft)) { | 686 | v = fr & VT_VALMASK; |
| 699 | calcaddr(&base,&fc,&sign,1020,2); | 687 | if (fr & VT_LVAL || fr == VT_LOCAL) { |
| 688 | uint32_t base = 0xb; | ||
| 689 | if (v < VT_CONST) { | ||
| 690 | base = intr(v); | ||
| 691 | v = VT_LOCAL; | ||
| 692 | fc = sign = 0; | ||
| 693 | } else if (v == VT_CONST) { | ||
| 694 | v1.type.t = ft; | ||
| 695 | v1.r = fr & ~VT_LVAL; | ||
| 696 | v1.c.ul = sv->c.ul; | ||
| 697 | v1.sym = sv->sym; | ||
| 698 | load(base = 14, &v1); | ||
| 699 | fc = sign = 0; | ||
| 700 | v = VT_LOCAL; | ||
| 701 | } | ||
| 702 | if (v == VT_LOCAL) { | ||
| 703 | if (is_float(ft)) { | ||
| 704 | calcaddr(&base, &fc, &sign, 1020, 2); | ||
| 700 | #ifdef TCC_ARM_VFP | 705 | #ifdef TCC_ARM_VFP |
| 701 | op=0xED000A00; /* fsts */ | 706 | op = 0xED000A00; /* fsts */ |
| 702 | if(!sign) | 707 | if (!sign) |
| 703 | op|=0x800000; | 708 | op |= 0x800000; |
| 704 | if ((ft & VT_BTYPE) != VT_FLOAT) | 709 | if ((ft & VT_BTYPE) != VT_FLOAT) |
| 705 | op|=0x100; /* fsts -> fstd */ | 710 | op |= 0x100; /* fsts -> fstd */ |
| 706 | o(op|(vfpr(r)<<12)|(fc>>2)|(base<<16)); | 711 | o(op | (vfpr(r) << 12) | (fc >> 2) | (base << 16)); |
| 707 | #else | 712 | #else |
| 708 | op=0xED000100; | 713 | op = 0xED000100; |
| 709 | if(!sign) | 714 | if (!sign) |
| 710 | op|=0x800000; | 715 | op |= 0x800000; |
| 711 | #if LDOUBLE_SIZE == 8 | 716 | #if LDOUBLE_SIZE == 8 |
| 712 | if ((ft & VT_BTYPE) != VT_FLOAT) | 717 | if ((ft & VT_BTYPE) != VT_FLOAT) |
| 713 | op|=0x8000; | 718 | op |= 0x8000; |
| 714 | #else | 719 | #else |
| 715 | if ((ft & VT_BTYPE) == VT_DOUBLE) | 720 | if ((ft & VT_BTYPE) == VT_DOUBLE) |
| 716 | op|=0x8000; | 721 | op |= 0x8000; |
| 717 | if ((ft & VT_BTYPE) == VT_LDOUBLE) | 722 | if ((ft & VT_BTYPE) == VT_LDOUBLE) |
| 718 | op|=0x400000; | 723 | op |= 0x400000; |
| 719 | #endif | 724 | #endif |
| 720 | o(op|(fpr(r)<<12)|(fc>>2)|(base<<16)); | 725 | o(op | (fpr(r) << 12) | (fc >> 2) | (base << 16)); |
| 721 | #endif | 726 | #endif |
| 722 | return; | 727 | return; |
| 723 | } else if((ft & VT_BTYPE) == VT_SHORT) { | 728 | } else if ((ft & VT_BTYPE) == VT_SHORT) { |
| 724 | calcaddr(&base,&fc,&sign,255,0); | 729 | calcaddr(&base, &fc, &sign, 255, 0); |
| 725 | op=0xE14000B0; | 730 | op = 0xE14000B0; |
| 726 | if(!sign) | 731 | if (!sign) |
| 727 | op|=0x800000; | 732 | op |= 0x800000; |
| 728 | o(op|(intr(r)<<12)|(base<<16)|((fc&0xf0)<<4)|(fc&0xf)); | 733 | o(op | (intr(r) << 12) | (base << 16) | ((fc & 0xf0) << 4) | |
| 729 | } else { | 734 | (fc & 0xf)); |
| 730 | calcaddr(&base,&fc,&sign,4095,0); | 735 | } else { |
| 731 | op=0xE5000000; | 736 | calcaddr(&base, &fc, &sign, 4095, 0); |
| 732 | if(!sign) | 737 | op = 0xE5000000; |
| 733 | op|=0x800000; | 738 | if (!sign) |
| 734 | if ((ft & VT_BTYPE) == VT_BYTE || (ft & VT_BTYPE) == VT_BOOL) | 739 | op |= 0x800000; |
| 735 | op|=0x400000; | 740 | if ((ft & VT_BTYPE) == VT_BYTE || (ft & VT_BTYPE) == VT_BOOL) |
| 736 | o(op|(intr(r)<<12)|fc|(base<<16)); | 741 | op |= 0x400000; |
| 737 | } | 742 | o(op | (intr(r) << 12) | fc | (base << 16)); |
| 738 | return; | 743 | } |
| 744 | return; | ||
| 745 | } | ||
| 739 | } | 746 | } |
| 740 | } | 747 | tcc_error("store unimplemented"); |
| 741 | tcc_error("store unimplemented"); | ||
| 742 | } | 748 | } |
| 743 | 749 | ||
| 744 | static void gadd_sp(int val) | 750 | static void gadd_sp(int val) |
| 745 | { | 751 | { |
| 746 | stuff_const_harder(0xE28DD000,val); | 752 | stuff_const_harder(0xE28DD000, val); |
| 747 | } | 753 | } |
| 748 | 754 | ||
| 749 | /* 'is_jmp' is '1' if it is a jump */ | 755 | /* 'is_jmp' is '1' if it is a jump */ |
| 750 | static void gcall_or_jmp(int is_jmp) | 756 | static void gcall_or_jmp(int is_jmp) |
| 751 | { | 757 | { |
| 752 | int r; | 758 | int r; |
| 753 | if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { | 759 | if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { |
| 754 | uint32_t x; | 760 | uint32_t x; |
| 755 | /* constant case */ | 761 | /* constant case */ |
| 756 | x=encbranch(ind,ind+vtop->c.ul,0); | 762 | x = encbranch(ind, ind + vtop->c.ul, 0); |
| 757 | if(x) { | 763 | if (x) { |
| 758 | if (vtop->r & VT_SYM) { | 764 | if (vtop->r & VT_SYM) { |
| 759 | /* relocation case */ | 765 | /* relocation case */ |
| 760 | greloc(cur_text_section, vtop->sym, ind, R_ARM_PC24); | 766 | greloc(cur_text_section, vtop->sym, ind, R_ARM_PC24); |
| 761 | } else | 767 | } else |
| 762 | put_elf_reloc(symtab_section, cur_text_section, ind, R_ARM_PC24, 0); | 768 | put_elf_reloc(symtab_section, cur_text_section, ind, R_ARM_PC24, |
| 763 | o(x|(is_jmp?0xE0000000:0xE1000000)); | 769 | 0); |
| 770 | o(x | (is_jmp ? 0xE0000000 : 0xE1000000)); | ||
| 771 | } else { | ||
| 772 | if (!is_jmp) | ||
| 773 | o(0xE28FE004); // add lr,pc,#4 | ||
| 774 | o(0xE51FF004); // ldr pc,[pc,#-4] | ||
| 775 | if (vtop->r & VT_SYM) | ||
| 776 | greloc(cur_text_section, vtop->sym, ind, R_ARM_ABS32); | ||
| 777 | o(vtop->c.ul); | ||
| 778 | } | ||
| 764 | } else { | 779 | } else { |
| 765 | if(!is_jmp) | 780 | /* otherwise, indirect call */ |
| 766 | o(0xE28FE004); // add lr,pc,#4 | 781 | r = gv(RC_INT); |
| 767 | o(0xE51FF004); // ldr pc,[pc,#-4] | 782 | if (!is_jmp) |
| 768 | if (vtop->r & VT_SYM) | 783 | o(0xE1A0E00F); // mov lr,pc |
| 769 | greloc(cur_text_section, vtop->sym, ind, R_ARM_ABS32); | 784 | o(0xE1A0F000 | intr(r)); // mov pc,r |
| 770 | o(vtop->c.ul); | ||
| 771 | } | 785 | } |
| 772 | } else { | ||
| 773 | /* otherwise, indirect call */ | ||
| 774 | r = gv(RC_INT); | ||
| 775 | if(!is_jmp) | ||
| 776 | o(0xE1A0E00F); // mov lr,pc | ||
| 777 | o(0xE1A0F000|intr(r)); // mov pc,r | ||
| 778 | } | ||
| 779 | } | 786 | } |
| 780 | 787 | ||
| 781 | /* Return whether a structure is an homogeneous float aggregate or not. | 788 | /* Return whether a structure is an homogeneous float aggregate or not. |
| @@ -783,27 +790,30 @@ static void gcall_or_jmp(int is_jmp) · 1 unmodified line | |||
| 783 | primitive float type and there is less than 4 elements. | 790 | primitive float type and there is less than 4 elements. |
| 784 | 791 | ||
| 785 | type: the type corresponding to the structure to be tested */ | 792 | type: the type corresponding to the structure to be tested */ |
| 786 | static int is_hgen_float_aggr(CType *type) | 793 | static int is_hgen_float_aggr(CType* type) |
| 787 | { | 794 | { |
| 788 | if ((type->t & VT_BTYPE) == VT_STRUCT) { | 795 | if ((type->t & VT_BTYPE) == VT_STRUCT) { |
| 789 | struct Sym *ref; | 796 | struct Sym* ref; |
| 790 | int btype, nb_fields = 0; | 797 | int btype, nb_fields = 0; |
| 791 | 798 | ||
| 792 | ref = type->ref->next; | 799 | ref = type->ref->next; |
| 793 | btype = ref->type.t & VT_BTYPE; | 800 | btype = ref->type.t & VT_BTYPE; |
| 794 | if (btype == VT_FLOAT || btype == VT_DOUBLE) { | 801 | if (btype == VT_FLOAT || btype == VT_DOUBLE) { |
| 795 | for(; ref && btype == (ref->type.t & VT_BTYPE); ref = ref->next, nb_fields++); | 802 | for (; ref && btype == (ref->type.t & VT_BTYPE); |
| 796 | return !ref && nb_fields <= 4; | 803 | ref = ref->next, nb_fields++) |
| 804 | ; | ||
| 805 | return !ref && nb_fields <= 4; | ||
| 806 | } | ||
| 797 | } | 807 | } |
| 798 | } | 808 | return 0; |
| 799 | return 0; | ||
| 800 | } | 809 | } |
| 801 | 810 | ||
| 802 | struct avail_regs { | 811 | struct avail_regs { |
| 803 | signed char avail[3]; /* 3 holes max with only float and double alignments */ | 812 | signed char |
| 804 | int first_hole; /* first available hole */ | 813 | avail[3]; /* 3 holes max with only float and double alignments */ |
| 805 | int last_hole; /* last available hole (none if equal to first_hole) */ | 814 | int first_hole; /* first available hole */ |
| 806 | int first_free_reg; /* next free register in the sequence, hole excluded */ | 815 | int last_hole; /* last available hole (none if equal to first_hole) */ |
| 816 | int first_free_reg; /* next free register in the sequence, hole excluded */ | ||
| 807 | }; | 817 | }; |
| 808 | 818 | ||
| 809 | #define AVAIL_REGS_INITIALIZER (struct avail_regs) { { 0, 0, 0}, 0, 0, 0 } | 819 | #define AVAIL_REGS_INITIALIZER (struct avail_regs) { { 0, 0, 0}, 0, 0, 0 } |
| @@ -817,40 +827,40 @@ struct avail_regs { · 7 unmodified lines | |||
| 817 | avregs: opaque structure to keep track of available VFP co-processor regs | 827 | avregs: opaque structure to keep track of available VFP co-processor regs |
| 818 | align: alignment contraints for the param, as returned by type_size() | 828 | align: alignment contraints for the param, as returned by type_size() |
| 819 | size: size of the parameter, as returned by type_size() */ | 829 | size: size of the parameter, as returned by type_size() */ |
| 820 | int assign_vfpreg(struct avail_regs *avregs, int align, int size) | 830 | int assign_vfpreg(struct avail_regs* avregs, int align, int size) |
| 821 | { | 831 | { |
| 822 | int first_reg = 0; | 832 | int first_reg = 0; |
| 823 | 833 | ||
| 824 | if (avregs->first_free_reg == -1) | 834 | if (avregs->first_free_reg == -1) |
| 835 | return -1; | ||
| 836 | if (align >> 3) { /* double alignment */ | ||
| 837 | first_reg = avregs->first_free_reg; | ||
| 838 | /* alignment contraint not respected so use next reg and record hole */ | ||
| 839 | if (first_reg & 1) | ||
| 840 | avregs->avail[avregs->last_hole++] = first_reg++; | ||
| 841 | } else { /* no special alignment (float or array of float) */ | ||
| 842 | /* if single float and a hole is available, assign the param to it */ | ||
| 843 | if (size == 4 && avregs->first_hole != avregs->last_hole) | ||
| 844 | return avregs->avail[avregs->first_hole++]; | ||
| 845 | else | ||
| 846 | first_reg = avregs->first_free_reg; | ||
| 847 | } | ||
| 848 | if (first_reg + size / 4 <= 16) { | ||
| 849 | avregs->first_free_reg = first_reg + size / 4; | ||
| 850 | return first_reg; | ||
| 851 | } | ||
| 852 | avregs->first_free_reg = -1; | ||
| 825 | return -1; | 853 | return -1; |
| 826 | if (align >> 3) { /* double alignment */ | ||
| 827 | first_reg = avregs->first_free_reg; | ||
| 828 | /* alignment contraint not respected so use next reg and record hole */ | ||
| 829 | if (first_reg & 1) | ||
| 830 | avregs->avail[avregs->last_hole++] = first_reg++; | ||
| 831 | } else { /* no special alignment (float or array of float) */ | ||
| 832 | /* if single float and a hole is available, assign the param to it */ | ||
| 833 | if (size == 4 && avregs->first_hole != avregs->last_hole) | ||
| 834 | return avregs->avail[avregs->first_hole++]; | ||
| 835 | else | ||
| 836 | first_reg = avregs->first_free_reg; | ||
| 837 | } | ||
| 838 | if (first_reg + size / 4 <= 16) { | ||
| 839 | avregs->first_free_reg = first_reg + size / 4; | ||
| 840 | return first_reg; | ||
| 841 | } | ||
| 842 | avregs->first_free_reg = -1; | ||
| 843 | return -1; | ||
| 844 | } | 854 | } |
| 845 | 855 | ||
| 846 | /* Returns whether all params need to be passed in core registers or not. | 856 | /* Returns whether all params need to be passed in core registers or not. |
| 847 | This is the case for function part of the runtime ABI. */ | 857 | This is the case for function part of the runtime ABI. */ |
| 848 | int floats_in_core_regs(SValue *sval) | 858 | int floats_in_core_regs(SValue* sval) |
| 849 | { | 859 | { |
| 850 | if (!sval->sym) | 860 | if (!sval->sym) |
| 851 | return 0; | 861 | return 0; |
| 852 | 862 | ||
| 853 | switch (sval->sym->v) { | 863 | switch (sval->sym->v) { |
| 854 | case TOK___floatundisf: | 864 | case TOK___floatundisf: |
| 855 | case TOK___floatundidf: | 865 | case TOK___floatundidf: |
| 856 | case TOK___fixunssfdi: | 866 | case TOK___fixunssfdi: |
| @@ -862,34 +872,36 @@ int floats_in_core_regs(SValue *sval) · 5 unmodified lines | |||
| 862 | case TOK___floatdidf: | 872 | case TOK___floatdidf: |
| 863 | case TOK___fixsfdi: | 873 | case TOK___fixsfdi: |
| 864 | case TOK___fixdfdi: | 874 | case TOK___fixdfdi: |
| 865 | return 1; | 875 | return 1; |
| 866 | 876 | ||
| 867 | default: | 877 | default: |
| 868 | return 0; | 878 | return 0; |
| 869 | } | 879 | } |
| 870 | } | 880 | } |
| 871 | 881 | ||
| 872 | ST_FUNC int regargs_nregs(RegArgs *args) | 882 | ST_FUNC int regargs_nregs(RegArgs* args) |
| 873 | { | 883 | { |
| 874 | return *args; | 884 | return *args; |
| 875 | } | 885 | } |
| 876 | 886 | ||
| 877 | /* Return the number of registers needed to return the struct, or 0 if | 887 | /* Return the number of registers needed to return the struct, or 0 if |
| 878 | returning via struct pointer. */ | 888 | returning via struct pointer. */ |
| 879 | ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize, RegArgs *args) { | 889 | ST_FUNC int gfunc_sret(CType* vt, int variadic, CType* ret, int* ret_align, |
| 890 | int* regsize, RegArgs* args) | ||
| 891 | { | ||
| 880 | #ifdef TCC_ARM_EABI | 892 | #ifdef TCC_ARM_EABI |
| 881 | int size, align; | 893 | int size, align; |
| 882 | size = type_size(vt, &align); | 894 | size = type_size(vt, &align); |
| 883 | if (float_abi == ARM_HARD_FLOAT && !variadic && | 895 | if (float_abi == ARM_HARD_FLOAT && !variadic && |
| 884 | (is_float(vt->t) || is_hgen_float_aggr(vt))) { | 896 | (is_float(vt->t) || is_hgen_float_aggr(vt))) { |
| 885 | *ret_align = 8; | 897 | *ret_align = 8; |
| 886 | *regsize = 8; | 898 | *regsize = 8; |
| 887 | ret->ref = NULL; | 899 | ret->ref = NULL; |
| 888 | ret->t = VT_DOUBLE; | 900 | ret->t = VT_DOUBLE; |
| 889 | *args = (size + 7) >> 3; | 901 | *args = (size + 7) >> 3; |
| 890 | } else if (size <= 4) { | 902 | } else if (size <= 4) { |
| 891 | *ret_align = 4; | 903 | *ret_align = 4; |
| 892 | *regsize = 4; | 904 | *regsize = 4; |
| 893 | ret->ref = NULL; | 905 | ret->ref = NULL; |
| 894 | ret->t = VT_INT; | 906 | ret->t = VT_INT; |
| 895 | *args = 1; | 907 | *args = 1; |
| @@ -912,32 +924,33 @@ ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int · 16 unmodified lines | |||
| 912 | - VFP_STRUCT_CLASS must come after VFP_CLASS. | 924 | - VFP_STRUCT_CLASS must come after VFP_CLASS. |
| 913 | See the comment for the main loop in copy_params() for the reason. */ | 925 | See the comment for the main loop in copy_params() for the reason. */ |
| 914 | enum reg_class { | 926 | enum reg_class { |
| 915 | STACK_CLASS = 0, | 927 | STACK_CLASS = 0, |
| 916 | CORE_STRUCT_CLASS, | 928 | CORE_STRUCT_CLASS, |
| 917 | VFP_CLASS, | 929 | VFP_CLASS, |
| 918 | VFP_STRUCT_CLASS, | 930 | VFP_STRUCT_CLASS, |
| 919 | CORE_CLASS, | 931 | CORE_CLASS, |
| 920 | NB_CLASSES | 932 | NB_CLASSES |
| 921 | }; | 933 | }; |
| 922 | 934 | ||
| 923 | struct param_plan { | 935 | struct param_plan { |
| 924 | int start; /* first reg or addr used depending on the class */ | 936 | int start; /* first reg or addr used depending on the class */ |
| 925 | int end; /* last reg used or next free addr depending on the class */ | 937 | int end; /* last reg used or next free addr depending on the class */ |
| 926 | SValue *sval; /* pointer to SValue on the value stack */ | 938 | SValue* sval; /* pointer to SValue on the value stack */ |
| 927 | struct param_plan *prev; /* previous element in this class */ | 939 | struct param_plan* prev; /* previous element in this class */ |
| 928 | }; | 940 | }; |
| 929 | 941 | ||
| 930 | struct plan { | 942 | struct plan { |
| 931 | struct param_plan *pplans; /* array of all the param plans */ | 943 | struct param_plan* pplans; /* array of all the param plans */ |
| 932 | struct param_plan *clsplans[NB_CLASSES]; /* per class lists of param plans */ | 944 | struct param_plan* |
| 945 | clsplans[NB_CLASSES]; /* per class lists of param plans */ | ||
| 933 | }; | 946 | }; |
| 934 | 947 | ||
| 935 | #define add_param_plan(plan,pplan,class) \ | 948 | #define add_param_plan(plan, pplan, class) \ |
| 936 | do { \ | 949 | do { \ |
| 937 | pplan.prev = plan->clsplans[class]; \ | 950 | pplan.prev = plan->clsplans[class]; \ |
| 938 | plan->pplans[plan ## _nb] = pplan; \ | 951 | plan->pplans[plan##_nb] = pplan; \ |
| 939 | plan->clsplans[class] = &plan->pplans[plan ## _nb++]; \ | 952 | plan->clsplans[class] = &plan->pplans[plan##_nb++]; \ |
| 940 | } while(0) | 953 | } while (0) |
| 941 | 954 | ||
| 942 | /* Assign parameters to registers and stack with alignment according to the | 955 | /* Assign parameters to registers and stack with alignment according to the |
| 943 | rules in the procedure call standard for the ARM architecture (AAPCS). | 956 | rules in the procedure call standard for the ARM architecture (AAPCS). |
| @@ -956,90 +969,93 @@ struct plan { · 12 unmodified lines | |||
| 956 | Note: this function allocated an array in plan->pplans with tcc_malloc. It | 969 | Note: this function allocated an array in plan->pplans with tcc_malloc. It |
| 957 | is the responsibility of the caller to free this array once used (ie not | 970 | is the responsibility of the caller to free this array once used (ie not |
| 958 | before copy_params). */ | 971 | before copy_params). */ |
| 959 | static int assign_regs(int nb_args, int float_abi, struct plan *plan, int *todo) | 972 | static int assign_regs(int nb_args, int float_abi, struct plan* plan, int* todo) |
| 960 | { | 973 | { |
| 961 | int i, size, align; | 974 | int i, size, align; |
| 962 | int ncrn /* next core register number */, nsaa /* next stacked argument address*/; | 975 | int ncrn /* next core register number */, |
| 963 | int plan_nb = 0; | 976 | nsaa /* next stacked argument address*/; |
| 964 | struct param_plan pplan; | 977 | int plan_nb = 0; |
| 965 | struct avail_regs avregs = AVAIL_REGS_INITIALIZER; | 978 | struct param_plan pplan; |
| 966 | 979 | struct avail_regs avregs = AVAIL_REGS_INITIALIZER; | |
| 967 | ncrn = nsaa = 0; | 980 | |
| 968 | *todo = 0; | 981 | ncrn = nsaa = 0; |
| 969 | plan->pplans = tcc_malloc(nb_args * sizeof(*plan->pplans)); | 982 | *todo = 0; |
| 970 | memset(plan->clsplans, 0, sizeof(plan->clsplans)); | 983 | plan->pplans = tcc_malloc(nb_args * sizeof(*plan->pplans)); |
| 971 | for(i = nb_args; i-- ;) { | 984 | memset(plan->clsplans, 0, sizeof(plan->clsplans)); |
| 972 | int j, start_vfpreg = 0; | 985 | for (i = nb_args; i--;) { |
| 973 | CType type = vtop[-i].type; | 986 | int j, start_vfpreg = 0; |
| 974 | type.t &= ~VT_ARRAY; | 987 | CType type = vtop[-i].type; |
| 975 | size = type_size(&type, &align); | 988 | type.t &= ~VT_ARRAY; |
| 976 | size = (size + 3) & ~3; | 989 | size = type_size(&type, &align); |
| 977 | align = (align + 3) & ~3; | 990 | size = (size + 3) & ~3; |
| 978 | switch(vtop[-i].type.t & VT_BTYPE) { | 991 | align = (align + 3) & ~3; |
| 979 | case VT_STRUCT: | 992 | switch (vtop[-i].type.t & VT_BTYPE) { |
| 980 | case VT_FLOAT: | 993 | case VT_STRUCT: |
| 981 | case VT_DOUBLE: | 994 | case VT_FLOAT: |
| 982 | case VT_LDOUBLE: | 995 | case VT_DOUBLE: |
| 983 | if (float_abi == ARM_HARD_FLOAT) { | 996 | case VT_LDOUBLE: |
| 984 | int is_hfa = 0; /* Homogeneous float aggregate */ | 997 | if (float_abi == ARM_HARD_FLOAT) { |
| 985 | 998 | int is_hfa = 0; /* Homogeneous float aggregate */ | |
| 986 | if (is_float(vtop[-i].type.t) | 999 | |
| 987 | || (is_hfa = is_hgen_float_aggr(&vtop[-i].type))) { | 1000 | if (is_float(vtop[-i].type.t) || |
| 988 | int end_vfpreg; | 1001 | (is_hfa = is_hgen_float_aggr(&vtop[-i].type))) { |
| 989 | 1002 | int end_vfpreg; | |
| 990 | start_vfpreg = assign_vfpreg(&avregs, align, size); | 1003 | |
| 991 | end_vfpreg = start_vfpreg + ((size - 1) >> 2); | 1004 | start_vfpreg = assign_vfpreg(&avregs, align, size); |
| 992 | if (start_vfpreg >= 0) { | 1005 | end_vfpreg = start_vfpreg + ((size - 1) >> 2); |
| 993 | pplan = (struct param_plan) {start_vfpreg, end_vfpreg, &vtop[-i]}; | 1006 | if (start_vfpreg >= 0) { |
| 994 | if (is_hfa) | 1007 | pplan = (struct param_plan){start_vfpreg, end_vfpreg, |
| 995 | add_param_plan(plan, pplan, VFP_STRUCT_CLASS); | 1008 | &vtop[-i]}; |
| 996 | else | 1009 | if (is_hfa) |
| 997 | add_param_plan(plan, pplan, VFP_CLASS); | 1010 | add_param_plan(plan, pplan, VFP_STRUCT_CLASS); |
| 1011 | else | ||
| 1012 | add_param_plan(plan, pplan, VFP_CLASS); | ||
| 1013 | continue; | ||
| 1014 | } else | ||
| 1015 | break; | ||
| 1016 | } | ||
| 1017 | } | ||
| 1018 | ncrn = (ncrn + (align - 1) / 4) & ~((align / 4) - 1); | ||
| 1019 | if (ncrn + size / 4 <= 4 || (ncrn < 4 && start_vfpreg != -1)) { | ||
| 1020 | /* The parameter is allocated both in core register and on | ||
| 1021 | * stack. As | ||
| 1022 | * such, it can be of either class: it would either be the last of | ||
| 1023 | * CORE_STRUCT_CLASS or the first of STACK_CLASS. */ | ||
| 1024 | for (j = ncrn; j < 4 && j < ncrn + size / 4; j++) | ||
| 1025 | *todo |= (1 << j); | ||
| 1026 | pplan = (struct param_plan){ncrn, j, &vtop[-i]}; | ||
| 1027 | add_param_plan(plan, pplan, CORE_STRUCT_CLASS); | ||
| 1028 | ncrn += size / 4; | ||
| 1029 | if (ncrn > 4) | ||
| 1030 | nsaa = (ncrn - 4) * 4; | ||
| 1031 | } else { | ||
| 1032 | ncrn = 4; | ||
| 1033 | break; | ||
| 1034 | } | ||
| 998 | continue; | 1035 | continue; |
| 999 | } else | 1036 | default: |
| 1000 | break; | 1037 | if (ncrn < 4) { |
| 1001 | } | 1038 | int is_long = (vtop[-i].type.t & VT_BTYPE) == VT_LLONG; |
| 1002 | } | 1039 | |
| 1003 | ncrn = (ncrn + (align-1)/4) & ~((align/4) - 1); | 1040 | if (is_long) { |
| 1004 | if (ncrn + size/4 <= 4 || (ncrn < 4 && start_vfpreg != -1)) { | 1041 | ncrn = (ncrn + 1) & -2; |
| 1005 | /* The parameter is allocated both in core register and on stack. As | 1042 | if (ncrn == 4) |
| 1006 | * such, it can be of either class: it would either be the last of | 1043 | break; |
| 1007 | * CORE_STRUCT_CLASS or the first of STACK_CLASS. */ | 1044 | } |
| 1008 | for (j = ncrn; j < 4 && j < ncrn + size / 4; j++) | 1045 | pplan = (struct param_plan){ncrn, ncrn, &vtop[-i]}; |
| 1009 | *todo|=(1<<j); | 1046 | ncrn++; |
| 1010 | pplan = (struct param_plan) {ncrn, j, &vtop[-i]}; | 1047 | if (is_long) |
| 1011 | add_param_plan(plan, pplan, CORE_STRUCT_CLASS); | 1048 | pplan.end = ncrn++; |
| 1012 | ncrn += size/4; | 1049 | add_param_plan(plan, pplan, CORE_CLASS); |
| 1013 | if (ncrn > 4) | 1050 | continue; |
| 1014 | nsaa = (ncrn - 4) * 4; | 1051 | } |
| 1015 | } else { | ||
| 1016 | ncrn = 4; | ||
| 1017 | break; | ||
| 1018 | } | ||
| 1019 | continue; | ||
| 1020 | default: | ||
| 1021 | if (ncrn < 4) { | ||
| 1022 | int is_long = (vtop[-i].type.t & VT_BTYPE) == VT_LLONG; | ||
| 1023 | |||
| 1024 | if (is_long) { | ||
| 1025 | ncrn = (ncrn + 1) & -2; | ||
| 1026 | if (ncrn == 4) | ||
| 1027 | break; | ||
| 1028 | } | 1052 | } |
| 1029 | pplan = (struct param_plan) {ncrn, ncrn, &vtop[-i]}; | 1053 | nsaa = (nsaa + (align - 1)) & ~(align - 1); |
| 1030 | ncrn++; | 1054 | pplan = (struct param_plan){nsaa, nsaa + size, &vtop[-i]}; |
| 1031 | if (is_long) | 1055 | add_param_plan(plan, pplan, STACK_CLASS); |
| 1032 | pplan.end = ncrn++; | 1056 | nsaa += size; /* size already rounded up before */ |
| 1033 | add_param_plan(plan, pplan, CORE_CLASS); | ||
| 1034 | continue; | ||
| 1035 | } | ||
| 1036 | } | 1057 | } |
| 1037 | nsaa = (nsaa + (align - 1)) & ~(align - 1); | 1058 | return nsaa; |
| 1038 | pplan = (struct param_plan) {nsaa, nsaa + size, &vtop[-i]}; | ||
| 1039 | add_param_plan(plan, pplan, STACK_CLASS); | ||
| 1040 | nsaa += size; /* size already rounded up before */ | ||
| 1041 | } | ||
| 1042 | return nsaa; | ||
| 1043 | } | 1059 | } |
| 1044 | 1060 | ||
| 1045 | #undef add_param_plan | 1061 | #undef add_param_plan |
| @@ -1052,156 +1068,165 @@ static int assign_regs(int nb_args, int float_abi, struct plan *plan, int *todo) · 6 unmodified lines | |||
| 1052 | todo: a bitmap indicating what core reg will hold a parameter | 1068 | todo: a bitmap indicating what core reg will hold a parameter |
| 1053 | 1069 | ||
| 1054 | Returns the number of SValue added by this function on the value stack */ | 1070 | Returns the number of SValue added by this function on the value stack */ |
| 1055 | static int copy_params(int nb_args, struct plan *plan, int todo) | 1071 | static int copy_params(int nb_args, struct plan* plan, int todo) |
| 1056 | { | 1072 | { |
| 1057 | int size, align, r, i, nb_extra_sval = 0; | 1073 | int size, align, r, i, nb_extra_sval = 0; |
| 1058 | struct param_plan *pplan; | 1074 | struct param_plan* pplan; |
| 1059 | 1075 | ||
| 1060 | /* Several constraints require parameters to be copied in a specific order: | 1076 | /* Several constraints require parameters to be copied in a specific order: |
| 1061 | - structures are copied to the stack before being loaded in a reg; | 1077 | - structures are copied to the stack before being loaded in a reg; |
| 1062 | - floats loaded to an odd numbered VFP reg are first copied to the | 1078 | - floats loaded to an odd numbered VFP reg are first copied to the |
| 1063 | preceding even numbered VFP reg and then moved to the next VFP reg. | 1079 | preceding even numbered VFP reg and then moved to the next VFP reg. |
| 1064 | 1080 | ||
| 1065 | It is thus important that: | 1081 | It is thus important that: |
| 1066 | - structures assigned to core regs must be copied after parameters | 1082 | - structures assigned to core regs must be copied after parameters |
| 1067 | assigned to the stack but before structures assigned to VFP regs because | 1083 | assigned to the stack but before structures assigned to VFP regs |
| 1068 | a structure can lie partly in core registers and partly on the stack; | 1084 | because a structure can lie partly in core registers and partly on |
| 1069 | - parameters assigned to the stack and all structures be copied before | 1085 | the stack; |
| 1070 | parameters assigned to a core reg since copying a parameter to the stack | 1086 | - parameters assigned to the stack and all structures be copied before |
| 1071 | require using a core reg; | 1087 | parameters assigned to a core reg since copying a parameter to the |
| 1072 | - parameters assigned to VFP regs be copied before structures assigned to | 1088 | stack require using a core reg; |
| 1073 | VFP regs as the copy might use an even numbered VFP reg that already | 1089 | - parameters assigned to VFP regs be copied before structures assigned to |
| 1074 | holds part of a structure. */ | 1090 | VFP regs as the copy might use an even numbered VFP reg that already |
| 1075 | for(i = 0; i < NB_CLASSES; i++) { | 1091 | holds part of a structure. */ |
| 1076 | for(pplan = plan->clsplans[i]; pplan; pplan = pplan->prev) { | 1092 | for (i = 0; i < NB_CLASSES; i++) { |
| 1077 | vpushv(pplan->sval); | 1093 | for (pplan = plan->clsplans[i]; pplan; pplan = pplan->prev) { |
| 1078 | pplan->sval->r = pplan->sval->r2 = VT_CONST; /* disable entry */ | 1094 | vpushv(pplan->sval); |
| 1079 | switch(i) { | 1095 | pplan->sval->r = pplan->sval->r2 = VT_CONST; /* disable entry */ |
| 1080 | case STACK_CLASS: | 1096 | switch (i) { |
| 1081 | case CORE_STRUCT_CLASS: | 1097 | case STACK_CLASS: |
| 1082 | case VFP_STRUCT_CLASS: | 1098 | case CORE_STRUCT_CLASS: |
| 1083 | if ((pplan->sval->type.t & VT_BTYPE) == VT_STRUCT) { | 1099 | case VFP_STRUCT_CLASS: |
| 1084 | int padding = 0; | 1100 | if ((pplan->sval->type.t & VT_BTYPE) == VT_STRUCT) { |
| 1085 | size = type_size(&pplan->sval->type, &align); | 1101 | int padding = 0; |
| 1086 | /* align to stack align size */ | 1102 | size = type_size(&pplan->sval->type, &align); |
| 1087 | size = (size + 3) & ~3; | 1103 | /* align to stack align size */ |
| 1088 | if (i == STACK_CLASS && pplan->prev) | 1104 | size = (size + 3) & ~3; |
| 1089 | padding = pplan->start - pplan->prev->end; | 1105 | if (i == STACK_CLASS && pplan->prev) |
| 1090 | size += padding; /* Add padding if any */ | 1106 | padding = pplan->start - pplan->prev->end; |
| 1091 | /* allocate the necessary size on stack */ | 1107 | size += padding; /* Add padding if any */ |
| 1092 | gadd_sp(-size); | 1108 | /* allocate the necessary size on stack */ |
| 1093 | /* generate structure store */ | 1109 | gadd_sp(-size); |
| 1094 | r = get_reg(RC_INT); | 1110 | /* generate structure store */ |
| 1095 | o(0xE28D0000|(intr(r)<<12)|padding); /* add r, sp, padding */ | 1111 | r = get_reg(RC_INT); |
| 1096 | vset(&vtop->type, r | VT_LVAL, 0); | 1112 | o(0xE28D0000 | (intr(r) << 12) | |
| 1097 | vswap(); | 1113 | padding); /* add r, sp, padding */ |
| 1098 | vstore(); /* memcpy to current sp + potential padding */ | 1114 | vset(&vtop->type, r | VT_LVAL, 0); |
| 1099 | 1115 | vswap(); | |
| 1100 | /* Homogeneous float aggregate are loaded to VFP registers | 1116 | vstore(); /* memcpy to current sp + potential padding */ |
| 1101 | immediately since there is no way of loading data in multiple | 1117 | |
| 1102 | non consecutive VFP registers as what is done for other | 1118 | /* Homogeneous float aggregate are loaded to VFP registers |
| 1103 | structures (see the use of todo). */ | 1119 | immediately since there is no way of loading data in |
| 1104 | if (i == VFP_STRUCT_CLASS) { | 1120 | multiple non consecutive VFP registers as what is done |
| 1105 | int first = pplan->start, nb = pplan->end - first + 1; | 1121 | for other structures (see the use of todo). */ |
| 1106 | /* vpop.32 {pplan->start, ..., pplan->end} */ | 1122 | if (i == VFP_STRUCT_CLASS) { |
| 1107 | o(0xECBD0A00|(first&1)<<22|(first>>1)<<12|nb); | 1123 | int first = pplan->start, nb = pplan->end - first + 1; |
| 1108 | /* No need to write the register used to a SValue since VFP regs | 1124 | /* vpop.32 {pplan->start, ..., pplan->end} */ |
| 1109 | cannot be used for gcall_or_jmp */ | 1125 | o(0xECBD0A00 | (first & 1) << 22 | (first >> 1) << 12 | |
| 1110 | } | 1126 | nb); |
| 1111 | } else { | 1127 | /* No need to write the register used to a SValue since |
| 1112 | if (is_float(pplan->sval->type.t)) { | 1128 | VFP regs cannot be used for gcall_or_jmp */ |
| 1129 | } | ||
| 1130 | } else { | ||
| 1131 | if (is_float(pplan->sval->type.t)) { | ||
| 1113 | #ifdef TCC_ARM_VFP | 1132 | #ifdef TCC_ARM_VFP |
| 1114 | r = vfpr(gv(RC_FLOAT)) << 12; | 1133 | r = vfpr(gv(RC_FLOAT)) << 12; |
| 1115 | if ((pplan->sval->type.t & VT_BTYPE) == VT_FLOAT) | 1134 | if ((pplan->sval->type.t & VT_BTYPE) == VT_FLOAT) |
| 1116 | size = 4; | 1135 | size = 4; |
| 1117 | else { | 1136 | else { |
| 1118 | size = 8; | 1137 | size = 8; |
| 1119 | r |= 0x101; /* vpush.32 -> vpush.64 */ | 1138 | r |= 0x101; /* vpush.32 -> vpush.64 */ |
| 1120 | } | 1139 | } |
| 1121 | o(0xED2D0A01 + r); /* vpush */ | 1140 | o(0xED2D0A01 + r); /* vpush */ |
| 1122 | #else | 1141 | #else |
| 1123 | r = fpr(gv(RC_FLOAT)) << 12; | 1142 | r = fpr(gv(RC_FLOAT)) << 12; |
| 1124 | if ((pplan->sval->type.t & VT_BTYPE) == VT_FLOAT) | 1143 | if ((pplan->sval->type.t & VT_BTYPE) == VT_FLOAT) |
| 1125 | size = 4; | 1144 | size = 4; |
| 1126 | else if ((pplan->sval->type.t & VT_BTYPE) == VT_DOUBLE) | 1145 | else if ((pplan->sval->type.t & VT_BTYPE) == VT_DOUBLE) |
| 1127 | size = 8; | 1146 | size = 8; |
| 1128 | else | 1147 | else |
| 1129 | size = LDOUBLE_SIZE; | 1148 | size = LDOUBLE_SIZE; |
| 1130 | 1149 | ||
| 1131 | if (size == 12) | 1150 | if (size == 12) |
| 1132 | r |= 0x400000; | 1151 | r |= 0x400000; |
| 1133 | else if(size == 8) | 1152 | else if (size == 8) |
| 1134 | r|=0x8000; | 1153 | r |= 0x8000; |
| 1135 | 1154 | ||
| 1136 | o(0xED2D0100|r|(size>>2)); /* some kind of vpush for FPA */ | 1155 | o(0xED2D0100 | r | (size >> 2)); /* some kind of vpush for FPA */ |
| 1137 | #endif | 1156 | #endif |
| 1138 | } else { | 1157 | } else { |
| 1139 | /* simple type (currently always same size) */ | 1158 | /* simple type (currently always same size) */ |
| 1140 | /* XXX: implicit cast ? */ | 1159 | /* XXX: implicit cast ? */ |
| 1141 | size=4; | 1160 | size = 4; |
| 1142 | if ((pplan->sval->type.t & VT_BTYPE) == VT_LLONG) { | 1161 | if ((pplan->sval->type.t & VT_BTYPE) == VT_LLONG) { |
| 1143 | lexpand_nr(); | 1162 | lexpand_nr(); |
| 1144 | size = 8; | 1163 | size = 8; |
| 1145 | r = gv(RC_INT); | 1164 | r = gv(RC_INT); |
| 1146 | o(0xE52D0004|(intr(r)<<12)); /* push r */ | 1165 | o(0xE52D0004 | (intr(r) << 12)); /* push r */ |
| 1147 | vtop--; | 1166 | vtop--; |
| 1148 | } | 1167 | } |
| 1149 | r = gv(RC_INT); | 1168 | r = gv(RC_INT); |
| 1150 | o(0xE52D0004|(intr(r)<<12)); /* push r */ | 1169 | o(0xE52D0004 | (intr(r) << 12)); /* push r */ |
| 1170 | } | ||
| 1171 | if (i == STACK_CLASS && pplan->prev) | ||
| 1172 | gadd_sp(pplan->prev->end - | ||
| 1173 | pplan->start); /* Add padding if any */ | ||
| 1174 | } | ||
| 1175 | break; | ||
| 1176 | |||
| 1177 | case VFP_CLASS: | ||
| 1178 | gv(regmask(TREG_F0 + (pplan->start >> 1))); | ||
| 1179 | if (pplan->start & | ||
| 1180 | 1) { /* Must be in upper part of double register */ | ||
| 1181 | o(0xEEF00A40 | ((pplan->start >> 1) << 12) | | ||
| 1182 | (pplan->start >> 1)); /* vmov.f32 s(n+1), sn */ | ||
| 1183 | vtop->r = | ||
| 1184 | VT_CONST; /* avoid being saved on stack by gv for next | ||
| 1185 | float */ | ||
| 1186 | } | ||
| 1187 | break; | ||
| 1188 | |||
| 1189 | case CORE_CLASS: | ||
| 1190 | if ((pplan->sval->type.t & VT_BTYPE) == VT_LLONG) { | ||
| 1191 | lexpand_nr(); | ||
| 1192 | gv(regmask(pplan->end)); | ||
| 1193 | pplan->sval->r2 = vtop->r; | ||
| 1194 | vtop--; | ||
| 1195 | } | ||
| 1196 | gv(regmask(pplan->start)); | ||
| 1197 | /* Mark register as used so that gcall_or_jmp use another one | ||
| 1198 | (regs >=4 are free as never used to pass parameters) */ | ||
| 1199 | pplan->sval->r = vtop->r; | ||
| 1200 | break; | ||
| 1151 | } | 1201 | } |
| 1152 | if (i == STACK_CLASS && pplan->prev) | ||
| 1153 | gadd_sp(pplan->prev->end - pplan->start); /* Add padding if any */ | ||
| 1154 | } | ||
| 1155 | break; | ||
| 1156 | |||
| 1157 | case VFP_CLASS: | ||
| 1158 | gv(regmask(TREG_F0 + (pplan->start >> 1))); | ||
| 1159 | if (pplan->start & 1) { /* Must be in upper part of double register */ | ||
| 1160 | o(0xEEF00A40|((pplan->start>>1)<<12)|(pplan->start>>1)); /* vmov.f32 s(n+1), sn */ | ||
| 1161 | vtop->r = VT_CONST; /* avoid being saved on stack by gv for next float */ | ||
| 1162 | } | ||
| 1163 | break; | ||
| 1164 | |||
| 1165 | case CORE_CLASS: | ||
| 1166 | if ((pplan->sval->type.t & VT_BTYPE) == VT_LLONG) { | ||
| 1167 | lexpand_nr(); | ||
| 1168 | gv(regmask(pplan->end)); | ||
| 1169 | pplan->sval->r2 = vtop->r; | ||
| 1170 | vtop--; | 1202 | vtop--; |
| 1171 | } | 1203 | } |
| 1172 | gv(regmask(pplan->start)); | ||
| 1173 | /* Mark register as used so that gcall_or_jmp use another one | ||
| 1174 | (regs >=4 are free as never used to pass parameters) */ | ||
| 1175 | pplan->sval->r = vtop->r; | ||
| 1176 | break; | ||
| 1177 | } | ||
| 1178 | vtop--; | ||
| 1179 | } | 1204 | } |
| 1180 | } | 1205 | |
| 1181 | 1206 | /* Manually free remaining registers since next parameters are loaded | |
| 1182 | /* Manually free remaining registers since next parameters are loaded | 1207 | * manually, without the help of gv(int). */ |
| 1183 | * manually, without the help of gv(int). */ | 1208 | save_regs(nb_args); |
| 1184 | save_regs(nb_args); | 1209 | |
| 1185 | 1210 | if (todo) { | |
| 1186 | if(todo) { | 1211 | o(0xE8BD0000 | todo); /* pop {todo} */ |
| 1187 | o(0xE8BD0000|todo); /* pop {todo} */ | 1212 | for (pplan = plan->clsplans[CORE_STRUCT_CLASS]; pplan; |
| 1188 | for(pplan = plan->clsplans[CORE_STRUCT_CLASS]; pplan; pplan = pplan->prev) { | 1213 | pplan = pplan->prev) { |
| 1189 | int r; | 1214 | int r; |
| 1190 | pplan->sval->r = pplan->start; | 1215 | pplan->sval->r = pplan->start; |
| 1191 | /* An SValue can only pin 2 registers at best (r and r2) but a structure | 1216 | /* An SValue can only pin 2 registers at best (r and r2) but a |
| 1192 | can occupy more than 2 registers. Thus, we need to push on the value | 1217 | structure can occupy more than 2 registers. Thus, we need to |
| 1193 | stack some fake parameter to have on SValue for each registers used | 1218 | push on the value stack some fake parameter to have on SValue |
| 1194 | by a structure (r2 is not used). */ | 1219 | for each registers used by a structure (r2 is not used). */ |
| 1195 | for (r = pplan->start + 1; r <= pplan->end; r++) { | 1220 | for (r = pplan->start + 1; r <= pplan->end; r++) { |
| 1196 | if (todo & (1 << r)) { | 1221 | if (todo & (1 << r)) { |
| 1197 | nb_extra_sval++; | 1222 | nb_extra_sval++; |
| 1198 | vpushi(0); | 1223 | vpushi(0); |
| 1199 | vtop->r = r; | 1224 | vtop->r = r; |
| 1225 | } | ||
| 1226 | } | ||
| 1200 | } | 1227 | } |
| 1201 | } | ||
| 1202 | } | 1228 | } |
| 1203 | } | 1229 | return nb_extra_sval; |
| 1204 | return nb_extra_sval; | ||
| 1205 | } | 1230 | } |
| 1206 | 1231 | ||
| 1207 | /* Generate function call. The function address is pushed first, then | 1232 | /* Generate function call. The function address is pushed first, then |
| @@ -1209,733 +1234,738 @@ static int copy_params(int nb_args, struct plan *plan, int todo) · 1 unmodified line | |||
| 1209 | parameters and the function address. */ | 1234 | parameters and the function address. */ |
| 1210 | void gfunc_call(int nb_args) | 1235 | void gfunc_call(int nb_args) |
| 1211 | { | 1236 | { |
| 1212 | int r, args_size; | 1237 | int r, args_size; |
| 1213 | int def_float_abi = float_abi; | 1238 | int def_float_abi = float_abi; |
| 1214 | int todo; | 1239 | int todo; |
| 1215 | struct plan plan; | 1240 | struct plan plan; |
| 1216 | 1241 | ||
| 1217 | #ifdef TCC_ARM_EABI | 1242 | #ifdef TCC_ARM_EABI |
| 1218 | int variadic; | 1243 | int variadic; |
| 1219 | 1244 | ||
| 1220 | if (float_abi == ARM_HARD_FLOAT) { | 1245 | if (float_abi == ARM_HARD_FLOAT) { |
| 1221 | variadic = (vtop[-nb_args].type.ref->c == FUNC_ELLIPSIS); | 1246 | variadic = (vtop[-nb_args].type.ref->c == FUNC_ELLIPSIS); |
| 1222 | if (variadic || floats_in_core_regs(&vtop[-nb_args])) | 1247 | if (variadic || floats_in_core_regs(&vtop[-nb_args])) |
| 1223 | float_abi = ARM_SOFTFP_FLOAT; | 1248 | float_abi = ARM_SOFTFP_FLOAT; |
| 1224 | } | 1249 | } |
| 1225 | #endif | 1250 | #endif |
| 1226 | /* cannot let cpu flags if other instruction are generated. Also avoid leaving | 1251 | /* cannot let cpu flags if other instruction are generated. Also avoid |
| 1227 | VT_JMP anywhere except on the top of the stack because it would complicate | 1252 | leaving VT_JMP anywhere except on the top of the stack because it |
| 1228 | the code generator. */ | 1253 | would complicate the code generator. */ |
| 1229 | r = vtop->r & VT_VALMASK; | 1254 | r = vtop->r & VT_VALMASK; |
| 1230 | if (r == VT_CMP || (r & ~1) == VT_JMP) | 1255 | if (r == VT_CMP || (r & ~1) == VT_JMP) |
| 1231 | gv(RC_INT); | 1256 | gv(RC_INT); |
| 1232 | 1257 | ||
| 1233 | args_size = assign_regs(nb_args, float_abi, &plan, &todo); | 1258 | args_size = assign_regs(nb_args, float_abi, &plan, &todo); |
| 1234 | 1259 | ||
| 1235 | #ifdef TCC_ARM_EABI | 1260 | #ifdef TCC_ARM_EABI |
| 1236 | if (args_size & 7) { /* Stack must be 8 byte aligned at fct call for EABI */ | 1261 | if (args_size & 7) { /* Stack must be 8 byte aligned at fct call for EABI */ |
| 1237 | args_size = (args_size + 7) & ~7; | 1262 | args_size = (args_size + 7) & ~7; |
| 1238 | o(0xE24DD004); /* sub sp, sp, #4 */ | 1263 | o(0xE24DD004); /* sub sp, sp, #4 */ |
| 1239 | } | 1264 | } |
| 1240 | #endif | 1265 | #endif |
| 1241 | 1266 | ||
| 1242 | nb_args += copy_params(nb_args, &plan, todo); | 1267 | nb_args += copy_params(nb_args, &plan, todo); |
| 1243 | tcc_free(plan.pplans); | 1268 | tcc_free(plan.pplans); |
| 1244 | 1269 | ||
| 1245 | /* Move fct SValue on top as required by gcall_or_jmp */ | 1270 | /* Move fct SValue on top as required by gcall_or_jmp */ |
| 1246 | vrotb(nb_args + 1); | 1271 | vrotb(nb_args + 1); |
| 1247 | gcall_or_jmp(0); | 1272 | gcall_or_jmp(0); |
| 1248 | if (args_size) | 1273 | if (args_size) |
| 1249 | gadd_sp(args_size); /* pop all parameters passed on the stack */ | 1274 | gadd_sp(args_size); /* pop all parameters passed on the stack */ |
| 1250 | #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP) | 1275 | #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP) |
| 1251 | if(float_abi == ARM_SOFTFP_FLOAT && is_float(vtop->type.ref->type.t)) { | 1276 | if (float_abi == ARM_SOFTFP_FLOAT && is_float(vtop->type.ref->type.t)) { |
| 1252 | if((vtop->type.ref->type.t & VT_BTYPE) == VT_FLOAT) { | 1277 | if ((vtop->type.ref->type.t & VT_BTYPE) == VT_FLOAT) { |
| 1253 | o(0xEE000A10); /*vmov s0, r0 */ | 1278 | o(0xEE000A10); /*vmov s0, r0 */ |
| 1254 | } else { | 1279 | } else { |
| 1255 | o(0xEE000B10); /* vmov.32 d0[0], r0 */ | 1280 | o(0xEE000B10); /* vmov.32 d0[0], r0 */ |
| 1256 | o(0xEE201B10); /* vmov.32 d0[1], r1 */ | 1281 | o(0xEE201B10); /* vmov.32 d0[1], r1 */ |
| 1282 | } | ||
| 1257 | } | 1283 | } |
| 1258 | } | ||
| 1259 | #endif | 1284 | #endif |
| 1260 | vtop -= nb_args + 1; /* Pop all params and fct address from value stack */ | 1285 | vtop -= nb_args + 1; /* Pop all params and fct address from value stack */ |
| 1261 | leaffunc = 0; /* we are calling a function, so we aren't in a leaf function */ | 1286 | leaffunc = |
| 1262 | float_abi = def_float_abi; | 1287 | 0; /* we are calling a function, so we aren't in a leaf function */ |
| 1288 | float_abi = def_float_abi; | ||
| 1263 | } | 1289 | } |
| 1264 | 1290 | ||
| 1265 | /* generate function prolog of type 't' */ | 1291 | /* generate function prolog of type 't' */ |
| 1266 | void gfunc_prolog(CType *func_type) | 1292 | void gfunc_prolog(CType* func_type) |
| 1267 | { | 1293 | { |
| 1268 | Sym *sym,*sym2; | 1294 | Sym* sym, *sym2; |
| 1269 | int n, nf, size, align, rs, struct_ret = 0; | 1295 | int n, nf, size, align, rs, struct_ret = 0; |
| 1270 | int addr, pn, sn; /* pn=core, sn=stack */ | 1296 | int addr, pn, sn; /* pn=core, sn=stack */ |
| 1271 | CType ret_type; | 1297 | CType ret_type; |
| 1272 | RegArgs dummy; | 1298 | RegArgs dummy; |
| 1273 | 1299 | ||
| 1274 | #ifdef TCC_ARM_EABI | 1300 | #ifdef TCC_ARM_EABI |
| 1275 | struct avail_regs avregs = AVAIL_REGS_INITIALIZER; | 1301 | struct avail_regs avregs = AVAIL_REGS_INITIALIZER; |
| 1276 | #endif | 1302 | #endif |
| 1277 | 1303 | ||
| 1278 | sym = func_type->ref; | 1304 | sym = func_type->ref; |
| 1279 | func_vt = sym->type; | 1305 | func_vt = sym->type; |
| 1280 | func_var = (func_type->ref->c == FUNC_ELLIPSIS); | 1306 | func_var = (func_type->ref->c == FUNC_ELLIPSIS); |
| 1281 | 1307 | ||
| 1282 | n = nf = 0; | 1308 | n = nf = 0; |
| 1283 | if ((func_vt.t & VT_BTYPE) == VT_STRUCT && | 1309 | if ((func_vt.t & VT_BTYPE) == VT_STRUCT && |
| 1284 | !gfunc_sret(&func_vt, func_var, &ret_type, &align, &rs, &dummy)) | 1310 | !gfunc_sret(&func_vt, func_var, &ret_type, &align, &rs, &dummy)) { |
| 1285 | { | 1311 | n++; |
| 1286 | n++; | 1312 | struct_ret = 1; |
| 1287 | struct_ret = 1; | 1313 | func_vc = 12; /* Offset from fp of the place to store the result */ |
| 1288 | func_vc = 12; /* Offset from fp of the place to store the result */ | 1314 | } |
| 1289 | } | 1315 | for (sym2 = sym->next; sym2 && (n < 4 || nf < 16); sym2 = sym2->next) { |
| 1290 | for(sym2 = sym->next; sym2 && (n < 4 || nf < 16); sym2 = sym2->next) { | 1316 | size = type_size(&sym2->type, &align); |
| 1291 | size = type_size(&sym2->type, &align); | ||
| 1292 | #ifdef TCC_ARM_EABI | 1317 | #ifdef TCC_ARM_EABI |
| 1293 | if (float_abi == ARM_HARD_FLOAT && !func_var && | 1318 | if (float_abi == ARM_HARD_FLOAT && !func_var && |
| 1294 | (is_float(sym2->type.t) || is_hgen_float_aggr(&sym2->type))) { | 1319 | (is_float(sym2->type.t) || is_hgen_float_aggr(&sym2->type))) { |
| 1295 | int tmpnf = assign_vfpreg(&avregs, align, size); | 1320 | int tmpnf = assign_vfpreg(&avregs, align, size); |
| 1296 | tmpnf += (size + 3) / 4; | 1321 | tmpnf += (size + 3) / 4; |
| 1297 | nf = (tmpnf > nf) ? tmpnf : nf; | 1322 | nf = (tmpnf > nf) ? tmpnf : nf; |
| 1298 | } else | 1323 | } else |
| 1299 | #endif | 1324 | #endif |
| 1300 | if (n < 4) | 1325 | if (n < 4) |
| 1301 | n += (size + 3) / 4; | 1326 | n += (size + 3) / 4; |
| 1302 | } | 1327 | } |
| 1303 | o(0xE1A0C00D); /* mov ip,sp */ | 1328 | o(0xE1A0C00D); /* mov ip,sp */ |
| 1304 | if (func_var) | 1329 | if (func_var) |
| 1305 | n=4; | 1330 | n = 4; |
| 1306 | if (n) { | 1331 | if (n) { |
| 1307 | if(n>4) | 1332 | if (n > 4) |
| 1308 | n=4; | 1333 | n = 4; |
| 1309 | #ifdef TCC_ARM_EABI | 1334 | #ifdef TCC_ARM_EABI |
| 1310 | n=(n+1)&-2; | 1335 | n = (n + 1) & -2; |
| 1311 | #endif | 1336 | #endif |
| 1312 | o(0xE92D0000|((1<<n)-1)); /* save r0-r4 on stack if needed */ | 1337 | o(0xE92D0000 | ((1 << n) - 1)); /* save r0-r4 on stack if needed */ |
| 1313 | } | 1338 | } |
| 1314 | if (nf) { | 1339 | if (nf) { |
| 1315 | if (nf>16) | 1340 | if (nf > 16) |
| 1316 | nf=16; | 1341 | nf = 16; |
| 1317 | nf=(nf+1)&-2; /* nf => HARDFLOAT => EABI */ | 1342 | nf = (nf + 1) & -2; /* nf => HARDFLOAT => EABI */ |
| 1318 | o(0xED2D0A00|nf); /* save s0-s15 on stack if needed */ | 1343 | o(0xED2D0A00 | nf); /* save s0-s15 on stack if needed */ |
| 1319 | } | 1344 | } |
| 1320 | o(0xE92D5800); /* save fp, ip, lr */ | 1345 | o(0xE92D5800); /* save fp, ip, lr */ |
| 1321 | o(0xE1A0B00D); /* mov fp, sp */ | 1346 | o(0xE1A0B00D); /* mov fp, sp */ |
| 1322 | func_sub_sp_offset = ind; | 1347 | func_sub_sp_offset = ind; |
| 1323 | o(0xE1A00000); /* nop, leave space for stack adjustment in epilog */ | 1348 | o(0xE1A00000); /* nop, leave space for stack adjustment in epilog */ |
| 1324 | 1349 | ||
| 1325 | #ifdef TCC_ARM_EABI | 1350 | #ifdef TCC_ARM_EABI |
| 1326 | if (float_abi == ARM_HARD_FLOAT) { | 1351 | if (float_abi == ARM_HARD_FLOAT) { |
| 1327 | func_vc += nf * 4; | 1352 | func_vc += nf * 4; |
| 1328 | avregs = AVAIL_REGS_INITIALIZER; | 1353 | avregs = AVAIL_REGS_INITIALIZER; |
| 1329 | } | 1354 | } |
| 1330 | #endif | 1355 | #endif |
| 1331 | pn = struct_ret, sn = 0; | 1356 | pn = struct_ret, sn = 0; |
| 1332 | while ((sym = sym->next)) { | 1357 | while ((sym = sym->next)) { |
| 1333 | CType *type; | 1358 | CType* type; |
| 1334 | type = &sym->type; | 1359 | type = &sym->type; |
| 1335 | size = type_size(type, &align); | 1360 | size = type_size(type, &align); |
| 1336 | size = (size + 3) >> 2; | 1361 | size = (size + 3) >> 2; |
| 1337 | align = (align + 3) & ~3; | 1362 | align = (align + 3) & ~3; |
| 1338 | #ifdef TCC_ARM_EABI | 1363 | #ifdef TCC_ARM_EABI |
| 1339 | if (float_abi == ARM_HARD_FLOAT && !func_var && (is_float(sym->type.t) | 1364 | if (float_abi == ARM_HARD_FLOAT && !func_var && |
| 1340 | || is_hgen_float_aggr(&sym->type))) { | 1365 | (is_float(sym->type.t) || is_hgen_float_aggr(&sym->type))) { |
| 1341 | int fpn = assign_vfpreg(&avregs, align, size << 2); | 1366 | int fpn = assign_vfpreg(&avregs, align, size << 2); |
| 1342 | if (fpn >= 0) | 1367 | if (fpn >= 0) |
| 1343 | addr = fpn * 4; | 1368 | addr = fpn * 4; |
| 1344 | else | 1369 | else |
| 1345 | goto from_stack; | 1370 | goto from_stack; |
| 1346 | } else | 1371 | } else |
| 1347 | #endif | 1372 | #endif |
| 1348 | if (pn < 4) { | 1373 | if (pn < 4) { |
| 1349 | #ifdef TCC_ARM_EABI | 1374 | #ifdef TCC_ARM_EABI |
| 1350 | pn = (pn + (align-1)/4) & -(align/4); | 1375 | pn = (pn + (align - 1) / 4) & -(align / 4); |
| 1351 | #endif | 1376 | #endif |
| 1352 | addr = (nf + pn) * 4; | 1377 | addr = (nf + pn) * 4; |
| 1353 | pn += size; | 1378 | pn += size; |
| 1354 | if (!sn && pn > 4) | 1379 | if (!sn && pn > 4) |
| 1355 | sn = (pn - 4); | 1380 | sn = (pn - 4); |
| 1356 | } else { | 1381 | } else { |
| 1357 | #ifdef TCC_ARM_EABI | 1382 | #ifdef TCC_ARM_EABI |
| 1358 | from_stack: | 1383 | from_stack: |
| 1359 | sn = (sn + (align-1)/4) & -(align/4); | 1384 | sn = (sn + (align - 1) / 4) & -(align / 4); |
| 1360 | #endif | 1385 | #endif |
| 1361 | addr = (n + nf + sn) * 4; | 1386 | addr = (n + nf + sn) * 4; |
| 1362 | sn += size; | 1387 | sn += size; |
| 1388 | } | ||
| 1389 | sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t), | ||
| 1390 | addr + 12); | ||
| 1363 | } | 1391 | } |
| 1364 | sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t), | 1392 | last_itod_magic = 0; |
| 1365 | addr + 12); | 1393 | leaffunc = 1; |
| 1366 | } | 1394 | loc = 0; |
| 1367 | last_itod_magic=0; | ||
| 1368 | leaffunc = 1; | ||
| 1369 | loc = 0; | ||
| 1370 | } | 1395 | } |
| 1371 | 1396 | ||
| 1372 | /* generate function epilog */ | 1397 | /* generate function epilog */ |
| 1373 | void gfunc_epilog(void) | 1398 | void gfunc_epilog(void) |
| 1374 | { | 1399 | { |
| 1375 | uint32_t x; | 1400 | uint32_t x; |
| 1376 | int diff; | 1401 | int diff; |
| 1377 | /* Copy float return value to core register if base standard is used and | 1402 | /* Copy float return value to core register if base standard is used and |
| 1378 | float computation is made with VFP */ | 1403 | float computation is made with VFP */ |
| 1379 | #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP) | 1404 | #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP) |
| 1380 | if ((float_abi == ARM_SOFTFP_FLOAT || func_var) && is_float(func_vt.t)) { | 1405 | if ((float_abi == ARM_SOFTFP_FLOAT || func_var) && is_float(func_vt.t)) { |
| 1381 | if((func_vt.t & VT_BTYPE) == VT_FLOAT) | 1406 | if ((func_vt.t & VT_BTYPE) == VT_FLOAT) |
| 1382 | o(0xEE100A10); /* fmrs r0, s0 */ | 1407 | o(0xEE100A10); /* fmrs r0, s0 */ |
| 1383 | else { | 1408 | else { |
| 1384 | o(0xEE100B10); /* fmrdl r0, d0 */ | 1409 | o(0xEE100B10); /* fmrdl r0, d0 */ |
| 1385 | o(0xEE301B10); /* fmrdh r1, d0 */ | 1410 | o(0xEE301B10); /* fmrdh r1, d0 */ |
| 1411 | } | ||
| 1386 | } | 1412 | } |
| 1387 | } | ||
| 1388 | #endif | 1413 | #endif |
| 1389 | o(0xE89BA800); /* restore fp, sp, pc */ | 1414 | o(0xE89BA800); /* restore fp, sp, pc */ |
| 1390 | diff = (-loc + 3) & -4; | 1415 | diff = (-loc + 3) & -4; |
| 1391 | #ifdef TCC_ARM_EABI | 1416 | #ifdef TCC_ARM_EABI |
| 1392 | if(!leaffunc) | 1417 | if (!leaffunc) |
| 1393 | diff = ((diff + 11) & -8) - 4; | 1418 | diff = ((diff + 11) & -8) - 4; |
| 1394 | #endif | 1419 | #endif |
| 1395 | if(diff > 0) { | 1420 | if (diff > 0) { |
| 1396 | x=stuff_const(0xE24BD000, diff); /* sub sp,fp,# */ | 1421 | x = stuff_const(0xE24BD000, diff); /* sub sp,fp,# */ |
| 1397 | if(x) | 1422 | if (x) |
| 1398 | *(uint32_t *)(cur_text_section->data + func_sub_sp_offset) = x; | 1423 | *(uint32_t*)(cur_text_section->data + func_sub_sp_offset) = x; |
| 1399 | else { | 1424 | else { |
| 1400 | int addr; | 1425 | int addr; |
| 1401 | addr=ind; | 1426 | addr = ind; |
| 1402 | o(0xE59FC004); /* ldr ip,[pc+4] */ | 1427 | o(0xE59FC004); /* ldr ip,[pc+4] */ |
| 1403 | o(0xE04BD00C); /* sub sp,fp,ip */ | 1428 | o(0xE04BD00C); /* sub sp,fp,ip */ |
| 1404 | o(0xE1A0F00E); /* mov pc,lr */ | 1429 | o(0xE1A0F00E); /* mov pc,lr */ |
| 1405 | o(diff); | 1430 | o(diff); |
| 1406 | *(uint32_t *)(cur_text_section->data + func_sub_sp_offset) = 0xE1000000|encbranch(func_sub_sp_offset,addr,1); | 1431 | *(uint32_t*)(cur_text_section->data + func_sub_sp_offset) = |
| 1432 | 0xE1000000 | encbranch(func_sub_sp_offset, addr, 1); | ||
| 1433 | } | ||
| 1407 | } | 1434 | } |
| 1408 | } | ||
| 1409 | } | 1435 | } |
| 1410 | 1436 | ||
| 1411 | /* generate a jump to a label */ | 1437 | /* generate a jump to a label */ |
| 1412 | int gjmp(int t) | 1438 | int gjmp(int t) |
| 1413 | { | 1439 | { |
| 1414 | int r; | 1440 | int r; |
| 1415 | r=ind; | 1441 | r = ind; |
| 1416 | o(0xE0000000|encbranch(r,t,1)); | 1442 | o(0xE0000000 | encbranch(r, t, 1)); |
| 1417 | return r; | 1443 | return r; |
| 1418 | } | 1444 | } |
| 1419 | 1445 | ||
| 1420 | /* generate a jump to a fixed address */ | 1446 | /* generate a jump to a fixed address */ |
| 1421 | void gjmp_addr(int a) | 1447 | void gjmp_addr(int a) |
| 1422 | { | 1448 | { |
| 1423 | gjmp(a); | 1449 | gjmp(a); |
| 1424 | } | 1450 | } |
| 1425 | 1451 | ||
| 1426 | /* generate a test. set 'inv' to invert test. Stack entry is popped */ | 1452 | /* generate a test. set 'inv' to invert test. Stack entry is popped */ |
| 1427 | int gtst(int inv, int t) | 1453 | int gtst(int inv, int t) |
| 1428 | { | 1454 | { |
| 1429 | int v, r; | 1455 | int v, r; |
| 1430 | uint32_t op; | 1456 | uint32_t op; |
| 1431 | v = vtop->r & VT_VALMASK; | 1457 | v = vtop->r & VT_VALMASK; |
| 1432 | r=ind; | 1458 | r = ind; |
| 1433 | if (v == VT_CMP) { | 1459 | if (v == VT_CMP) { |
| 1434 | op=mapcc(inv?negcc(vtop->c.i):vtop->c.i); | 1460 | op = mapcc(inv ? negcc(vtop->c.i) : vtop->c.i); |
| 1435 | op|=encbranch(r,t,1); | 1461 | op |= encbranch(r, t, 1); |
| 1436 | o(op); | 1462 | o(op); |
| 1437 | t=r; | 1463 | t = r; |
| 1438 | } else if (v == VT_JMP || v == VT_JMPI) { | 1464 | } else if (v == VT_JMP || v == VT_JMPI) { |
| 1439 | if ((v & 1) == inv) { | 1465 | if ((v & 1) == inv) { |
| 1440 | if(!vtop->c.i) | 1466 | if (!vtop->c.i) |
| 1441 | vtop->c.i=t; | 1467 | vtop->c.i = t; |
| 1442 | else { | 1468 | else { |
| 1443 | uint32_t *x; | 1469 | uint32_t* x; |
| 1444 | int p,lp; | 1470 | int p, lp; |
| 1445 | if(t) { | 1471 | if (t) { |
| 1446 | p = vtop->c.i; | 1472 | p = vtop->c.i; |
| 1447 | do { | 1473 | do { |
| 1448 | p = decbranch(lp=p); | 1474 | p = decbranch(lp = p); |
| 1449 | } while(p); | 1475 | } while (p); |
| 1450 | x = (uint32_t *)(cur_text_section->data + lp); | 1476 | x = (uint32_t*)(cur_text_section->data + lp); |
| 1451 | *x &= 0xff000000; | 1477 | *x &= 0xff000000; |
| 1452 | *x |= encbranch(lp,t,1); | 1478 | *x |= encbranch(lp, t, 1); |
| 1453 | } | 1479 | } |
| 1454 | t = vtop->c.i; | 1480 | t = vtop->c.i; |
| 1455 | } | 1481 | } |
| 1456 | } else { | 1482 | } else { |
| 1457 | t = gjmp(t); | 1483 | t = gjmp(t); |
| 1458 | gsym(vtop->c.i); | 1484 | gsym(vtop->c.i); |
| 1485 | } | ||
| 1459 | } | 1486 | } |
| 1460 | } | 1487 | vtop--; |
| 1461 | vtop--; | 1488 | return t; |
| 1462 | return t; | ||
| 1463 | } | 1489 | } |
| 1464 | 1490 | ||
| 1465 | /* generate an integer binary operation */ | 1491 | /* generate an integer binary operation */ |
| 1466 | void gen_opi(int op) | 1492 | void gen_opi(int op) |
| 1467 | { | 1493 | { |
| 1468 | int c, func = 0; | 1494 | int c, func = 0; |
| 1469 | uint32_t opc = 0, r, fr; | 1495 | uint32_t opc = 0, r, fr; |
| 1470 | unsigned short retreg = REG_IRET; | 1496 | unsigned short retreg = REG_IRET; |
| 1471 | 1497 | ||
| 1472 | c=0; | 1498 | c = 0; |
| 1473 | switch(op) { | 1499 | switch (op) { |
| 1474 | case '+': | 1500 | case '+': |
| 1475 | opc = 0x8; | 1501 | opc = 0x8; |
| 1476 | c=1; | 1502 | c = 1; |
| 1477 | break; | 1503 | break; |
| 1478 | case TOK_ADDC1: /* add with carry generation */ | 1504 | case TOK_ADDC1: /* add with carry generation */ |
| 1479 | opc = 0x9; | 1505 | opc = 0x9; |
| 1480 | c=1; | 1506 | c = 1; |
| 1481 | break; | 1507 | break; |
| 1482 | case '-': | 1508 | case '-': |
| 1483 | opc = 0x4; | 1509 | opc = 0x4; |
| 1484 | c=1; | 1510 | c = 1; |
| 1485 | break; | 1511 | break; |
| 1486 | case TOK_SUBC1: /* sub with carry generation */ | 1512 | case TOK_SUBC1: /* sub with carry generation */ |
| 1487 | opc = 0x5; | 1513 | opc = 0x5; |
| 1488 | c=1; | 1514 | c = 1; |
| 1489 | break; | 1515 | break; |
| 1490 | case TOK_ADDC2: /* add with carry use */ | 1516 | case TOK_ADDC2: /* add with carry use */ |
| 1491 | opc = 0xA; | 1517 | opc = 0xA; |
| 1492 | c=1; | 1518 | c = 1; |
| 1493 | break; | 1519 | break; |
| 1494 | case TOK_SUBC2: /* sub with carry use */ | 1520 | case TOK_SUBC2: /* sub with carry use */ |
| 1495 | opc = 0xC; | 1521 | opc = 0xC; |
| 1496 | c=1; | 1522 | c = 1; |
| 1497 | break; | 1523 | break; |
| 1498 | case '&': | 1524 | case '&': |
| 1499 | opc = 0x0; | 1525 | opc = 0x0; |
| 1500 | c=1; | 1526 | c = 1; |
| 1501 | break; | 1527 | break; |
| 1502 | case '^': | 1528 | case '^': |
| 1503 | opc = 0x2; | 1529 | opc = 0x2; |
| 1504 | c=1; | 1530 | c = 1; |
| 1505 | break; | 1531 | break; |
| 1506 | case '|': | 1532 | case '|': |
| 1507 | opc = 0x18; | 1533 | opc = 0x18; |
| 1508 | c=1; | 1534 | c = 1; |
| 1509 | break; | 1535 | break; |
| 1510 | case '*': | 1536 | case '*': |
| 1511 | gv2(RC_INT, RC_INT); | 1537 | gv2(RC_INT, RC_INT); |
| 1512 | r = vtop[-1].r; | 1538 | r = vtop[-1].r; |
| 1513 | fr = vtop[0].r; | 1539 | fr = vtop[0].r; |
| 1514 | vtop--; | 1540 | vtop--; |
| 1515 | o(0xE0000090|(intr(r)<<16)|(intr(r)<<8)|intr(fr)); | 1541 | o(0xE0000090 | (intr(r) << 16) | (intr(r) << 8) | intr(fr)); |
| 1516 | return; | 1542 | return; |
| 1517 | case TOK_SHL: | 1543 | case TOK_SHL: |
| 1518 | opc = 0; | 1544 | opc = 0; |
| 1519 | c=2; | 1545 | c = 2; |
| 1520 | break; | 1546 | break; |
| 1521 | case TOK_SHR: | 1547 | case TOK_SHR: |
| 1522 | opc = 1; | 1548 | opc = 1; |
| 1523 | c=2; | 1549 | c = 2; |
| 1524 | break; | 1550 | break; |
| 1525 | case TOK_SAR: | 1551 | case TOK_SAR: |
| 1526 | opc = 2; | 1552 | opc = 2; |
| 1527 | c=2; | 1553 | c = 2; |
| 1528 | break; | 1554 | break; |
| 1529 | case '/': | 1555 | case '/': |
| 1530 | case TOK_PDIV: | 1556 | case TOK_PDIV: |
| 1531 | func=TOK___divsi3; | 1557 | func = TOK___divsi3; |
| 1532 | c=3; | 1558 | c = 3; |
| 1533 | break; | 1559 | break; |
| 1534 | case TOK_UDIV: | 1560 | case TOK_UDIV: |
| 1535 | func=TOK___udivsi3; | 1561 | func = TOK___udivsi3; |
| 1536 | c=3; | 1562 | c = 3; |
| 1537 | break; | 1563 | break; |
| 1538 | case '%': | 1564 | case '%': |
| 1539 | #ifdef TCC_ARM_EABI | 1565 | #ifdef TCC_ARM_EABI |
| 1540 | func=TOK___aeabi_idivmod; | 1566 | func = TOK___aeabi_idivmod; |
| 1541 | retreg=REG_LRET; | 1567 | retreg = REG_LRET; |
| 1542 | #else | 1568 | #else |
| 1543 | func=TOK___modsi3; | 1569 | func = TOK___modsi3; |
| 1544 | #endif | 1570 | #endif |
| 1545 | c=3; | 1571 | c = 3; |
| 1546 | break; | 1572 | break; |
| 1547 | case TOK_UMOD: | 1573 | case TOK_UMOD: |
| 1548 | #ifdef TCC_ARM_EABI | 1574 | #ifdef TCC_ARM_EABI |
| 1549 | func=TOK___aeabi_uidivmod; | 1575 | func = TOK___aeabi_uidivmod; |
| 1550 | retreg=REG_LRET; | 1576 | retreg = REG_LRET; |
| 1551 | #else | 1577 | #else |
| 1552 | func=TOK___umodsi3; | 1578 | func = TOK___umodsi3; |
| 1553 | #endif | 1579 | #endif |
| 1554 | c=3; | 1580 | c = 3; |
| 1555 | break; | 1581 | break; |
| 1556 | case TOK_UMULL: | 1582 | case TOK_UMULL: |
| 1557 | gv2(RC_INT, RC_INT); | 1583 | gv2(RC_INT, RC_INT); |
| 1558 | r=intr(vtop[-1].r2=get_reg(RC_INT)); | 1584 | r = intr(vtop[-1].r2 = get_reg(RC_INT)); |
| 1559 | c=vtop[-1].r; | 1585 | c = vtop[-1].r; |
| 1560 | vtop[-1].r=get_reg_ex(RC_INT,regmask(c)); | 1586 | vtop[-1].r = get_reg_ex(RC_INT, regmask(c)); |
| 1561 | vtop--; | 1587 | vtop--; |
| 1562 | o(0xE0800090|(r<<16)|(intr(vtop->r)<<12)|(intr(c)<<8)|intr(vtop[1].r)); | 1588 | o(0xE0800090 | (r << 16) | (intr(vtop->r) << 12) | (intr(c) << 8) | |
| 1563 | return; | 1589 | intr(vtop[1].r)); |
| 1590 | return; | ||
| 1564 | default: | 1591 | default: |
| 1565 | opc = 0x15; | 1592 | opc = 0x15; |
| 1566 | c=1; | 1593 | c = 1; |
| 1567 | break; | 1594 | break; |
| 1568 | } | 1595 | } |
| 1569 | switch(c) { | 1596 | switch (c) { |
| 1570 | case 1: | 1597 | case 1: |
| 1571 | if((vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { | 1598 | if ((vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { |
| 1572 | if(opc == 4 || opc == 5 || opc == 0xc) { | 1599 | if (opc == 4 || opc == 5 || opc == 0xc) { |
| 1573 | vswap(); | 1600 | vswap(); |
| 1574 | opc|=2; // sub -> rsb | 1601 | opc |= 2; // sub -> rsb |
| 1575 | } | 1602 | } |
| 1576 | } | 1603 | } |
| 1577 | if ((vtop->r & VT_VALMASK) == VT_CMP || | 1604 | if ((vtop->r & VT_VALMASK) == VT_CMP || |
| 1578 | (vtop->r & (VT_VALMASK & ~1)) == VT_JMP) | 1605 | (vtop->r & (VT_VALMASK & ~1)) == VT_JMP) |
| 1579 | gv(RC_INT); | 1606 | gv(RC_INT); |
| 1580 | vswap(); | 1607 | vswap(); |
| 1581 | c=intr(gv(RC_INT)); | 1608 | c = intr(gv(RC_INT)); |
| 1582 | vswap(); | 1609 | vswap(); |
| 1583 | opc=0xE0000000|(opc<<20)|(c<<16); | 1610 | opc = 0xE0000000 | (opc << 20) | (c << 16); |
| 1584 | if((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { | 1611 | if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { |
| 1585 | uint32_t x; | 1612 | uint32_t x; |
| 1586 | x=stuff_const(opc|0x2000000,vtop->c.i); | 1613 | x = stuff_const(opc | 0x2000000, vtop->c.i); |
| 1587 | if(x) { | 1614 | if (x) { |
| 1588 | r=intr(vtop[-1].r=get_reg_ex(RC_INT,regmask(vtop[-1].r))); | 1615 | r = intr(vtop[-1].r = get_reg_ex(RC_INT, regmask(vtop[-1].r))); |
| 1589 | o(x|(r<<12)); | 1616 | o(x | (r << 12)); |
| 1590 | goto done; | 1617 | goto done; |
| 1591 | } | 1618 | } |
| 1592 | } | 1619 | } |
| 1593 | fr=intr(gv(RC_INT)); | 1620 | fr = intr(gv(RC_INT)); |
| 1594 | r=intr(vtop[-1].r=get_reg_ex(RC_INT,two2mask(vtop->r,vtop[-1].r))); | 1621 | r = intr(vtop[-1].r = |
| 1595 | o(opc|(r<<12)|fr); | 1622 | get_reg_ex(RC_INT, two2mask(vtop->r, vtop[-1].r))); |
| 1596 | done: | 1623 | o(opc | (r << 12) | fr); |
| 1597 | vtop--; | 1624 | done: |
| 1598 | if (op >= TOK_ULT && op <= TOK_GT) { | 1625 | vtop--; |
| 1599 | vtop->r = VT_CMP; | 1626 | if (op >= TOK_ULT && op <= TOK_GT) { |
| 1600 | vtop->c.i = op; | 1627 | vtop->r = VT_CMP; |
| 1601 | } | 1628 | vtop->c.i = op; |
| 1602 | break; | 1629 | } |
| 1630 | break; | ||
| 1603 | case 2: | 1631 | case 2: |
| 1604 | opc=0xE1A00000|(opc<<5); | 1632 | opc = 0xE1A00000 | (opc << 5); |
| 1605 | if ((vtop->r & VT_VALMASK) == VT_CMP || | 1633 | if ((vtop->r & VT_VALMASK) == VT_CMP || |
| 1606 | (vtop->r & (VT_VALMASK & ~1)) == VT_JMP) | 1634 | (vtop->r & (VT_VALMASK & ~1)) == VT_JMP) |
| 1607 | gv(RC_INT); | 1635 | gv(RC_INT); |
| 1608 | vswap(); | 1636 | vswap(); |
| 1609 | r=intr(gv(RC_INT)); | 1637 | r = intr(gv(RC_INT)); |
| 1610 | vswap(); | 1638 | vswap(); |
| 1611 | opc|=r; | 1639 | opc |= r; |
| 1612 | if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { | 1640 | if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { |
| 1613 | fr=intr(vtop[-1].r=get_reg_ex(RC_INT,regmask(vtop[-1].r))); | 1641 | fr = intr(vtop[-1].r = get_reg_ex(RC_INT, regmask(vtop[-1].r))); |
| 1614 | c = vtop->c.i & 0x1f; | 1642 | c = vtop->c.i & 0x1f; |
| 1615 | o(opc|(c<<7)|(fr<<12)); | 1643 | o(opc | (c << 7) | (fr << 12)); |
| 1616 | } else { | 1644 | } else { |
| 1617 | fr=intr(gv(RC_INT)); | 1645 | fr = intr(gv(RC_INT)); |
| 1618 | c=intr(vtop[-1].r=get_reg_ex(RC_INT,two2mask(vtop->r,vtop[-1].r))); | 1646 | c = intr(vtop[-1].r = |
| 1619 | o(opc|(c<<12)|(fr<<8)|0x10); | 1647 | get_reg_ex(RC_INT, two2mask(vtop->r, vtop[-1].r))); |
| 1620 | } | 1648 | o(opc | (c << 12) | (fr << 8) | 0x10); |
| 1621 | vtop--; | 1649 | } |
| 1622 | break; | 1650 | vtop--; |
| 1651 | break; | ||
| 1623 | case 3: | 1652 | case 3: |
| 1624 | vpush_global_sym(&func_old_type, func); | 1653 | vpush_global_sym(&func_old_type, func); |
| 1625 | vrott(3); | 1654 | vrott(3); |
| 1626 | gfunc_call(2); | 1655 | gfunc_call(2); |
| 1627 | vpushi(0); | 1656 | vpushi(0); |
| 1628 | vtop->r = retreg; | 1657 | vtop->r = retreg; |
| 1629 | break; | 1658 | break; |
| 1630 | default: | 1659 | default: |
| 1631 | tcc_error("gen_opi %i unimplemented!",op); | 1660 | tcc_error("gen_opi %i unimplemented!", op); |
| 1632 | } | 1661 | } |
| 1633 | } | 1662 | } |
| 1634 | 1663 | ||
| 1635 | #ifdef TCC_ARM_VFP | 1664 | #ifdef TCC_ARM_VFP |
| 1636 | static int is_zero(int i) | 1665 | static int is_zero(int i) |
| 1637 | { | 1666 | { |
| 1638 | if((vtop[i].r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST) | 1667 | if ((vtop[i].r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST) |
| 1639 | return 0; | 1668 | return 0; |
| 1640 | if (vtop[i].type.t == VT_FLOAT) | 1669 | if (vtop[i].type.t == VT_FLOAT) |
| 1641 | return (vtop[i].c.f == 0.f); | 1670 | return (vtop[i].c.f == 0.f); |
| 1642 | else if (vtop[i].type.t == VT_DOUBLE) | 1671 | else if (vtop[i].type.t == VT_DOUBLE) |
| 1643 | return (vtop[i].c.d == 0.0); | 1672 | return (vtop[i].c.d == 0.0); |
| 1644 | return (vtop[i].c.ld == 0.l); | 1673 | return (vtop[i].c.ld == 0.l); |
| 1645 | } | 1674 | } |
| 1646 | 1675 | ||
| 1647 | /* generate a floating point operation 'v = t1 op t2' instruction. The | 1676 | /* generate a floating point operation 'v = t1 op t2' instruction. The |
| 1648 | * two operands are guaranted to have the same floating point type */ | 1677 | * two operands are guaranted to have the same floating point type */ |
| 1649 | void gen_opf(int op) | 1678 | void gen_opf(int op) |
| 1650 | { | 1679 | { |
| 1651 | uint32_t x; | 1680 | uint32_t x; |
| 1652 | int fneg=0,r; | 1681 | int fneg = 0, r; |
| 1653 | x=0xEE000A00|T2CPR(vtop->type.t); | 1682 | x = 0xEE000A00 | T2CPR(vtop->type.t); |
| 1654 | switch(op) { | 1683 | switch (op) { |
| 1655 | case '+': | 1684 | case '+': |
| 1656 | if(is_zero(-1)) | 1685 | if (is_zero(-1)) |
| 1657 | vswap(); | 1686 | vswap(); |
| 1658 | if(is_zero(0)) { | 1687 | if (is_zero(0)) { |
| 1659 | vtop--; | 1688 | vtop--; |
| 1660 | return; | 1689 | return; |
| 1661 | } | 1690 | } |
| 1662 | x|=0x300000; | 1691 | x |= 0x300000; |
| 1663 | break; | 1692 | break; |
| 1664 | case '-': | 1693 | case '-': |
| 1665 | x|=0x300040; | 1694 | x |= 0x300040; |
| 1666 | if(is_zero(0)) { | 1695 | if (is_zero(0)) { |
| 1667 | vtop--; | 1696 | vtop--; |
| 1668 | return; | 1697 | return; |
| 1669 | } | 1698 | } |
| 1670 | if(is_zero(-1)) { | 1699 | if (is_zero(-1)) { |
| 1671 | x|=0x810000; /* fsubX -> fnegX */ | 1700 | x |= 0x810000; /* fsubX -> fnegX */ |
| 1672 | vswap(); | 1701 | vswap(); |
| 1673 | vtop--; | 1702 | vtop--; |
| 1674 | fneg=1; | 1703 | fneg = 1; |
| 1675 | } | 1704 | } |
| 1676 | break; | 1705 | break; |
| 1677 | case '*': | 1706 | case '*': |
| 1678 | x|=0x200000; | 1707 | x |= 0x200000; |
| 1679 | break; | 1708 | break; |
| 1680 | case '/': | 1709 | case '/': |
| 1681 | x|=0x800000; | 1710 | x |= 0x800000; |
| 1682 | break; | 1711 | break; |
| 1683 | default: | 1712 | default: |
| 1684 | if(op < TOK_ULT || op > TOK_GT) { | 1713 | if (op < TOK_ULT || op > TOK_GT) { |
| 1685 | tcc_error("unknown fp op %x!",op); | 1714 | tcc_error("unknown fp op %x!", op); |
| 1686 | return; | 1715 | return; |
| 1687 | } | 1716 | } |
| 1688 | if(is_zero(-1)) { | 1717 | if (is_zero(-1)) { |
| 1689 | vswap(); | 1718 | vswap(); |
| 1690 | switch(op) { | 1719 | switch(op) { |
| 1691 | case TOK_LT: op=TOK_GT; break; | 1720 | case TOK_LT: op = TOK_GT; break; |
| 1692 | case TOK_GE: op=TOK_ULE; break; | 1721 | case TOK_GE: op = TOK_ULE; break; |
| 1693 | case TOK_LE: op=TOK_GE; break; | 1722 | case TOK_LE: op = TOK_GE; break; |
| 1694 | case TOK_GT: op=TOK_ULT; break; | 1723 | case TOK_GT: op = TOK_ULT; break; |
| 1695 | } | 1724 | } |
| 1696 | } | 1725 | } |
| 1697 | x|=0xB40040; /* fcmpX */ | 1726 | x |= 0xB40040; /* fcmpX */ |
| 1698 | if(op!=TOK_EQ && op!=TOK_NE) | 1727 | if (op != TOK_EQ && op != TOK_NE) |
| 1699 | x|=0x80; /* fcmpX -> fcmpeX */ | 1728 | x |= 0x80; /* fcmpX -> fcmpeX */ |
| 1700 | if(is_zero(0)) { | 1729 | if (is_zero(0)) { |
| 1701 | vtop--; | 1730 | vtop--; |
| 1702 | o(x|0x10000|(vfpr(gv(RC_FLOAT))<<12)); /* fcmp(e)X -> fcmp(e)zX */ | 1731 | o(x | 0x10000 | |
| 1703 | } else { | 1732 | (vfpr(gv(RC_FLOAT)) << 12)); /* fcmp(e)X -> fcmp(e)zX */ |
| 1704 | x|=vfpr(gv(RC_FLOAT)); | 1733 | } else { |
| 1705 | vswap(); | 1734 | x |= vfpr(gv(RC_FLOAT)); |
| 1706 | o(x|(vfpr(gv(RC_FLOAT))<<12)); | 1735 | vswap(); |
| 1707 | vtop--; | 1736 | o(x | (vfpr(gv(RC_FLOAT)) << 12)); |
| 1708 | } | 1737 | vtop--; |
| 1709 | o(0xEEF1FA10); /* fmstat */ | 1738 | } |
| 1739 | o(0xEEF1FA10); /* fmstat */ | ||
| 1710 | 1740 | ||
| 1711 | switch(op) { | 1741 | switch(op) { |
| 1712 | case TOK_LE: op=TOK_ULE; break; | 1742 | case TOK_LE: op = TOK_ULE; break; |
| 1713 | case TOK_LT: op=TOK_ULT; break; | 1743 | case TOK_LT: op = TOK_ULT; break; |
| 1714 | case TOK_UGE: op=TOK_GE; break; | 1744 | case TOK_UGE: op = TOK_GE; break; |
| 1715 | case TOK_UGT: op=TOK_GT; break; | 1745 | case TOK_UGT: op = TOK_GT; break; |
| 1716 | } | 1746 | } |
| 1717 | 1747 | ||
| 1718 | vtop->r = VT_CMP; | 1748 | vtop->r = VT_CMP; |
| 1719 | vtop->c.i = op; | 1749 | vtop->c.i = op; |
| 1720 | return; | 1750 | return; |
| 1721 | } | 1751 | } |
| 1722 | r=gv(RC_FLOAT); | 1752 | r = gv(RC_FLOAT); |
| 1723 | x|=vfpr(r); | 1753 | x |= vfpr(r); |
| 1724 | r=regmask(r); | 1754 | r = regmask(r); |
| 1725 | if(!fneg) { | 1755 | if (!fneg) { |
| 1726 | int r2; | 1756 | int r2; |
| 1727 | vswap(); | 1757 | vswap(); |
| 1728 | r2=gv(RC_FLOAT); | 1758 | r2 = gv(RC_FLOAT); |
| 1729 | x|=vfpr(r2)<<16; | 1759 | x |= vfpr(r2) << 16; |
| 1730 | r|=regmask(r2); | 1760 | r |= regmask(r2); |
| 1731 | } | 1761 | } |
| 1732 | vtop->r=get_reg_ex(RC_FLOAT,r); | 1762 | vtop->r = get_reg_ex(RC_FLOAT, r); |
| 1733 | if(!fneg) | 1763 | if (!fneg) |
| 1734 | vtop--; | 1764 | vtop--; |
| 1735 | o(x|(vfpr(vtop->r)<<12)); | 1765 | o(x | (vfpr(vtop->r) << 12)); |
| 1736 | } | 1766 | } |
| 1737 | 1767 | ||
| 1738 | #else | 1768 | #else |
| 1739 | static uint32_t is_fconst() | 1769 | static uint32_t is_fconst() |
| 1740 | { | 1770 | { |
| 1741 | long double f; | 1771 | long double f; |
| 1742 | uint32_t r; | 1772 | uint32_t r; |
| 1743 | if((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST) | 1773 | if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST) |
| 1744 | return 0; | 1774 | return 0; |
| 1745 | if (vtop->type.t == VT_FLOAT) | 1775 | if (vtop->type.t == VT_FLOAT) |
| 1746 | f = vtop->c.f; | 1776 | f = vtop->c.f; |
| 1747 | else if (vtop->type.t == VT_DOUBLE) | 1777 | else if (vtop->type.t == VT_DOUBLE) |
| 1748 | f = vtop->c.d; | 1778 | f = vtop->c.d; |
| 1749 | else | 1779 | else |
| 1750 | f = vtop->c.ld; | 1780 | f = vtop->c.ld; |
| 1751 | if(!ieee_finite(f)) | 1781 | if (!ieee_finite(f)) |
| 1782 | return 0; | ||
| 1783 | r = 0x8; | ||
| 1784 | if (f < 0.0) { | ||
| 1785 | r = 0x18; | ||
| 1786 | f = -f; | ||
| 1787 | } | ||
| 1788 | if (f == 0.0) | ||
| 1789 | return r; | ||
| 1790 | if (f == 1.0) | ||
| 1791 | return r | 1; | ||
| 1792 | if (f == 2.0) | ||
| 1793 | return r | 2; | ||
| 1794 | if (f == 3.0) | ||
| 1795 | return r | 3; | ||
| 1796 | if (f == 4.0) | ||
| 1797 | return r | 4; | ||
| 1798 | if (f == 5.0) | ||
| 1799 | return r | 5; | ||
| 1800 | if (f == 0.5) | ||
| 1801 | return r | 6; | ||
| 1802 | if (f == 10.0) | ||
| 1803 | return r | 7; | ||
| 1752 | return 0; | 1804 | return 0; |
| 1753 | r=0x8; | ||
| 1754 | if(f<0.0) { | ||
| 1755 | r=0x18; | ||
| 1756 | f=-f; | ||
| 1757 | } | ||
| 1758 | if(f==0.0) | ||
| 1759 | return r; | ||
| 1760 | if(f==1.0) | ||
| 1761 | return r|1; | ||
| 1762 | if(f==2.0) | ||
| 1763 | return r|2; | ||
| 1764 | if(f==3.0) | ||
| 1765 | return r|3; | ||
| 1766 | if(f==4.0) | ||
| 1767 | return r|4; | ||
| 1768 | if(f==5.0) | ||
| 1769 | return r|5; | ||
| 1770 | if(f==0.5) | ||
| 1771 | return r|6; | ||
| 1772 | if(f==10.0) | ||
| 1773 | return r|7; | ||
| 1774 | return 0; | ||
| 1775 | } | 1805 | } |
| 1776 | 1806 | ||
| 1777 | /* generate a floating point operation 'v = t1 op t2' instruction. The | 1807 | /* generate a floating point operation 'v = t1 op t2' instruction. The |
| 1778 | two operands are guaranted to have the same floating point type */ | 1808 | two operands are guaranted to have the same floating point type */ |
| 1779 | void gen_opf(int op) | 1809 | void gen_opf(int op) |
| 1780 | { | 1810 | { |
| 1781 | uint32_t x, r, r2, c1, c2; | 1811 | uint32_t x, r, r2, c1, c2; |
| 1782 | //fputs("gen_opf\n",stderr); | 1812 | // fputs("gen_opf\n",stderr); |
| 1783 | vswap(); | 1813 | vswap(); |
| 1784 | c1 = is_fconst(); | 1814 | c1 = is_fconst(); |
| 1785 | vswap(); | 1815 | vswap(); |
| 1786 | c2 = is_fconst(); | 1816 | c2 = is_fconst(); |
| 1787 | x=0xEE000100; | 1817 | x = 0xEE000100; |
| 1788 | #if LDOUBLE_SIZE == 8 | 1818 | #if LDOUBLE_SIZE == 8 |
| 1789 | if ((vtop->type.t & VT_BTYPE) != VT_FLOAT) | 1819 | if ((vtop->type.t & VT_BTYPE) != VT_FLOAT) |
| 1790 | x|=0x80; | 1820 | x |= 0x80; |
| 1791 | #else | 1821 | #else |
| 1792 | if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) | 1822 | if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) |
| 1793 | x|=0x80; | 1823 | x |= 0x80; |
| 1794 | else if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) | 1824 | else if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) |
| 1795 | x|=0x80000; | 1825 | x |= 0x80000; |
| 1796 | #endif | 1826 | #endif |
| 1797 | switch(op) | 1827 | switch (op) { |
| 1798 | { | ||
| 1799 | case '+': | 1828 | case '+': |
| 1800 | if(!c2) { | 1829 | if (!c2) { |
| 1801 | vswap(); | 1830 | vswap(); |
| 1802 | c2=c1; | 1831 | c2 = c1; |
| 1803 | } | 1832 | } |
| 1804 | vswap(); | 1833 | vswap(); |
| 1805 | r=fpr(gv(RC_FLOAT)); | 1834 | r = fpr(gv(RC_FLOAT)); |
| 1806 | vswap(); | 1835 | vswap(); |
| 1807 | if(c2) { | 1836 | if (c2) { |
| 1808 | if(c2>0xf) | 1837 | if (c2 > 0xf) |
| 1809 | x|=0x200000; // suf | 1838 | x |= 0x200000; // suf |
| 1810 | r2=c2&0xf; | 1839 | r2 = c2 & 0xf; |
| 1811 | } else { | 1840 | } else { |
| 1812 | r2=fpr(gv(RC_FLOAT)); | 1841 | r2 = fpr(gv(RC_FLOAT)); |
| 1813 | } | 1842 | } |
| 1814 | break; | 1843 | break; |
| 1815 | case '-': | 1844 | case '-': |
| 1816 | if(c2) { | 1845 | if (c2) { |
| 1817 | if(c2<=0xf) | 1846 | if (c2 <= 0xf) |
| 1818 | x|=0x200000; // suf | 1847 | x |= 0x200000; // suf |
| 1819 | r2=c2&0xf; | 1848 | r2 = c2 & 0xf; |
| 1820 | vswap(); | 1849 | vswap(); |
| 1821 | r=fpr(gv(RC_FLOAT)); | 1850 | r = fpr(gv(RC_FLOAT)); |
| 1822 | vswap(); | 1851 | vswap(); |
| 1823 | } else if(c1 && c1<=0xf) { | 1852 | } else if (c1 && c1 <= 0xf) { |
| 1824 | x|=0x300000; // rsf | 1853 | x |= 0x300000; // rsf |
| 1825 | r2=c1; | 1854 | r2 = c1; |
| 1826 | r=fpr(gv(RC_FLOAT)); | 1855 | r = fpr(gv(RC_FLOAT)); |
| 1827 | vswap(); | 1856 | vswap(); |
| 1828 | } else { | 1857 | } else { |
| 1829 | x|=0x200000; // suf | 1858 | x |= 0x200000; // suf |
| 1830 | vswap(); | 1859 | vswap(); |
| 1831 | r=fpr(gv(RC_FLOAT)); | 1860 | r = fpr(gv(RC_FLOAT)); |
| 1832 | vswap(); | 1861 | vswap(); |
| 1833 | r2=fpr(gv(RC_FLOAT)); | 1862 | r2 = fpr(gv(RC_FLOAT)); |
| 1834 | } | 1863 | } |
| 1835 | break; | 1864 | break; |
| 1836 | case '*': | 1865 | case '*': |
| 1837 | if(!c2 || c2>0xf) { | 1866 | if (!c2 || c2 > 0xf) { |
| 1838 | vswap(); | 1867 | vswap(); |
| 1839 | c2=c1; | 1868 | c2 = c1; |
| 1840 | } | 1869 | } |
| 1841 | vswap(); | 1870 | vswap(); |
| 1842 | r=fpr(gv(RC_FLOAT)); | 1871 | r = fpr(gv(RC_FLOAT)); |
| 1843 | vswap(); | 1872 | vswap(); |
| 1844 | if(c2 && c2<=0xf) | 1873 | if (c2 && c2 <= 0xf) |
| 1845 | r2=c2; | 1874 | r2 = c2; |
| 1846 | else | 1875 | else |
| 1847 | r2=fpr(gv(RC_FLOAT)); | 1876 | r2 = fpr(gv(RC_FLOAT)); |
| 1848 | x|=0x100000; // muf | 1877 | x |= 0x100000; // muf |
| 1849 | break; | 1878 | break; |
| 1850 | case '/': | 1879 | case '/': |
| 1851 | if(c2 && c2<=0xf) { | 1880 | if (c2 && c2 <= 0xf) { |
| 1852 | x|=0x400000; // dvf | 1881 | x |= 0x400000; // dvf |
| 1853 | r2=c2; | 1882 | r2 = c2; |
| 1854 | vswap(); | 1883 | vswap(); |
| 1855 | r=fpr(gv(RC_FLOAT)); | 1884 | r = fpr(gv(RC_FLOAT)); |
| 1856 | vswap(); | 1885 | vswap(); |
| 1857 | } else if(c1 && c1<=0xf) { | 1886 | } else if (c1 && c1 <= 0xf) { |
| 1858 | x|=0x500000; // rdf | 1887 | x |= 0x500000; // rdf |
| 1859 | r2=c1; | 1888 | r2 = c1; |
| 1860 | r=fpr(gv(RC_FLOAT)); | 1889 | r = fpr(gv(RC_FLOAT)); |
| 1861 | vswap(); | 1890 | vswap(); |
| 1862 | } else { | 1891 | } else { |
| 1863 | x|=0x400000; // dvf | 1892 | x |= 0x400000; // dvf |
| 1864 | vswap(); | 1893 | vswap(); |
| 1865 | r=fpr(gv(RC_FLOAT)); | 1894 | r = fpr(gv(RC_FLOAT)); |
| 1866 | vswap(); | 1895 | vswap(); |
| 1867 | r2=fpr(gv(RC_FLOAT)); | 1896 | r2 = fpr(gv(RC_FLOAT)); |
| 1868 | } | 1897 | } |
| 1869 | break; | 1898 | break; |
| 1870 | default: | 1899 | default: |
| 1871 | if(op >= TOK_ULT && op <= TOK_GT) { | 1900 | if (op >= TOK_ULT && op <= TOK_GT) { |
| 1872 | x|=0xd0f110; // cmfe | 1901 | x |= 0xd0f110; // cmfe |
| 1873 | /* bug (intention?) in Linux FPU emulator | 1902 | /* bug (intention?) in Linux FPU emulator |
| 1874 | doesn't set carry if equal */ | 1903 | doesn't set carry if equal */ |
| 1875 | switch(op) { | 1904 | switch (op) { |
| 1876 | case TOK_ULT: | 1905 | case TOK_ULT: |
| 1877 | case TOK_UGE: | 1906 | case TOK_UGE: |
| 1878 | case TOK_ULE: | 1907 | case TOK_ULE: |
| 1879 | case TOK_UGT: | 1908 | case TOK_UGT: |
| 1880 | tcc_error("unsigned comparison on floats?"); | 1909 | tcc_error("unsigned comparison on floats?"); |
| 1881 | break; | 1910 | break; |
| 1882 | case TOK_LT: | 1911 | case TOK_LT: |
| 1883 | op=TOK_Nset; | 1912 | op = TOK_Nset; |
| 1884 | break; | 1913 | break; |
| 1885 | case TOK_LE: | 1914 | case TOK_LE: |
| 1886 | op=TOK_ULE; /* correct in unordered case only if AC bit in FPSR set */ | 1915 | op = TOK_ULE; /* correct in unordered case only if AC bit in |
| 1887 | break; | 1916 | FPSR set */ |
| 1888 | case TOK_EQ: | 1917 | break; |
| 1889 | case TOK_NE: | 1918 | case TOK_EQ: |
| 1890 | x&=~0x400000; // cmfe -> cmf | 1919 | case TOK_NE: |
| 1891 | break; | 1920 | x &= ~0x400000; // cmfe -> cmf |
| 1892 | } | 1921 | break; |
| 1893 | if(c1 && !c2) { | 1922 | } |
| 1894 | c2=c1; | 1923 | if (c1 && !c2) { |
| 1895 | vswap(); | 1924 | c2 = c1; |
| 1896 | switch(op) { | 1925 | vswap(); |
| 1897 | case TOK_Nset: | 1926 | switch (op) { |
| 1898 | op=TOK_GT; | 1927 | case TOK_Nset: |
| 1899 | break; | 1928 | op = TOK_GT; |
| 1900 | case TOK_GE: | 1929 | break; |
| 1901 | op=TOK_ULE; | 1930 | case TOK_GE: |
| 1902 | break; | 1931 | op = TOK_ULE; |
| 1903 | case TOK_ULE: | 1932 | break; |
| 1904 | op=TOK_GE; | 1933 | case TOK_ULE: |
| 1905 | break; | 1934 | op = TOK_GE; |
| 1906 | case TOK_GT: | 1935 | break; |
| 1907 | op=TOK_Nset; | 1936 | case TOK_GT: |
| 1908 | break; | 1937 | op = TOK_Nset; |
| 1909 | } | 1938 | break; |
| 1910 | } | 1939 | } |
| 1911 | vswap(); | 1940 | } |
| 1912 | r=fpr(gv(RC_FLOAT)); | 1941 | vswap(); |
| 1913 | vswap(); | 1942 | r = fpr(gv(RC_FLOAT)); |
| 1914 | if(c2) { | 1943 | vswap(); |
| 1915 | if(c2>0xf) | 1944 | if (c2) { |
| 1916 | x|=0x200000; | 1945 | if (c2 > 0xf) |
| 1917 | r2=c2&0xf; | 1946 | x |= 0x200000; |
| 1918 | } else { | 1947 | r2 = c2 & 0xf; |
| 1919 | r2=fpr(gv(RC_FLOAT)); | 1948 | } else { |
| 1920 | } | 1949 | r2 = fpr(gv(RC_FLOAT)); |
| 1921 | vtop[-1].r = VT_CMP; | 1950 | } |
| 1922 | vtop[-1].c.i = op; | 1951 | vtop[-1].r = VT_CMP; |
| 1923 | } else { | 1952 | vtop[-1].c.i = op; |
| 1924 | tcc_error("unknown fp op %x!",op); | 1953 | } else { |
| 1925 | return; | 1954 | tcc_error("unknown fp op %x!", op); |
| 1926 | } | 1955 | return; |
| 1927 | } | 1956 | } |
| 1928 | if(vtop[-1].r == VT_CMP) | 1957 | } |
| 1929 | c1=15; | 1958 | if (vtop[-1].r == VT_CMP) |
| 1930 | else { | 1959 | c1 = 15; |
| 1931 | c1=vtop->r; | 1960 | else { |
| 1932 | if(r2&0x8) | 1961 | c1 = vtop->r; |
| 1933 | c1=vtop[-1].r; | 1962 | if (r2 & 0x8) |
| 1934 | vtop[-1].r=get_reg_ex(RC_FLOAT,two2mask(vtop[-1].r,c1)); | 1963 | c1 = vtop[-1].r; |
| 1935 | c1=fpr(vtop[-1].r); | 1964 | vtop[-1].r = get_reg_ex(RC_FLOAT, two2mask(vtop[-1].r, c1)); |
| 1936 | } | 1965 | c1 = fpr(vtop[-1].r); |
| 1937 | vtop--; | 1966 | } |
| 1938 | o(x|(r<<16)|(c1<<12)|r2); | 1967 | vtop--; |
| 1968 | o(x | (r << 16) | (c1 << 12) | r2); | ||
| 1939 | } | 1969 | } |
| 1940 | #endif | 1970 | #endif |
| 1941 | 1971 | ||
| @@ -1943,177 +1973,186 @@ void gen_opf(int op) · 1 unmodified line | |||
| 1943 | and 'long long' cases. */ | 1973 | and 'long long' cases. */ |
| 1944 | ST_FUNC void gen_cvt_itof1(int t) | 1974 | ST_FUNC void gen_cvt_itof1(int t) |
| 1945 | { | 1975 | { |
| 1946 | uint32_t r, r2; | 1976 | uint32_t r, r2; |
| 1947 | int bt; | 1977 | int bt; |
| 1948 | bt=vtop->type.t & VT_BTYPE; | 1978 | bt = vtop->type.t & VT_BTYPE; |
| 1949 | if(bt == VT_INT || bt == VT_SHORT || bt == VT_BYTE) { | 1979 | if (bt == VT_INT || bt == VT_SHORT || bt == VT_BYTE) { |
| 1950 | #ifndef TCC_ARM_VFP | 1980 | #ifndef TCC_ARM_VFP |
| 1951 | uint32_t dsize = 0; | 1981 | uint32_t dsize = 0; |
| 1952 | #endif | 1982 | #endif |
| 1953 | r=intr(gv(RC_INT)); | 1983 | r = intr(gv(RC_INT)); |
| 1954 | #ifdef TCC_ARM_VFP | 1984 | #ifdef TCC_ARM_VFP |
| 1955 | r2=vfpr(vtop->r=get_reg(RC_FLOAT)); | 1985 | r2 = vfpr(vtop->r = get_reg(RC_FLOAT)); |
| 1956 | o(0xEE000A10|(r<<12)|(r2<<16)); /* fmsr */ | 1986 | o(0xEE000A10 | (r << 12) | (r2 << 16)); /* fmsr */ |
| 1957 | r2|=r2<<12; | 1987 | r2 |= r2 << 12; |
| 1958 | if(!(vtop->type.t & VT_UNSIGNED)) | 1988 | if (!(vtop->type.t & VT_UNSIGNED)) |
| 1959 | r2|=0x80; /* fuitoX -> fsituX */ | 1989 | r2 |= 0x80; /* fuitoX -> fsituX */ |
| 1960 | o(0xEEB80A40|r2|T2CPR(t)); /* fYitoX*/ | 1990 | o(0xEEB80A40 | r2 | T2CPR(t)); /* fYitoX*/ |
| 1961 | #else | 1991 | #else |
| 1962 | r2=fpr(vtop->r=get_reg(RC_FLOAT)); | 1992 | r2 = fpr(vtop->r = get_reg(RC_FLOAT)); |
| 1963 | if((t & VT_BTYPE) != VT_FLOAT) | 1993 | if ((t & VT_BTYPE) != VT_FLOAT) |
| 1964 | dsize=0x80; /* flts -> fltd */ | 1994 | dsize = 0x80; /* flts -> fltd */ |
| 1965 | o(0xEE000110|dsize|(r2<<16)|(r<<12)); /* flts */ | 1995 | o(0xEE000110 | dsize | (r2 << 16) | (r << 12)); /* flts */ |
| 1966 | if((vtop->type.t & (VT_UNSIGNED|VT_BTYPE)) == (VT_UNSIGNED|VT_INT)) { | 1996 | if ((vtop->type.t & (VT_UNSIGNED | VT_BTYPE)) == |
| 1967 | uint32_t off = 0; | 1997 | (VT_UNSIGNED | VT_INT)) { |
| 1968 | o(0xE3500000|(r<<12)); /* cmp */ | 1998 | uint32_t off = 0; |
| 1969 | r=fpr(get_reg(RC_FLOAT)); | 1999 | o(0xE3500000 | (r << 12)); /* cmp */ |
| 1970 | if(last_itod_magic) { | 2000 | r = fpr(get_reg(RC_FLOAT)); |
| 1971 | off=ind+8-last_itod_magic; | 2001 | if (last_itod_magic) { |
| 1972 | off/=4; | 2002 | off = ind + 8 - last_itod_magic; |
| 1973 | if(off>255) | 2003 | off /= 4; |
| 1974 | off=0; | 2004 | if (off > 255) |
| 1975 | } | 2005 | off = 0; |
| 1976 | o(0xBD1F0100|(r<<12)|off); /* ldflts */ | 2006 | } |
| 1977 | if(!off) { | 2007 | o(0xBD1F0100 | (r << 12) | off); /* ldflts */ |
| 1978 | o(0xEA000000); /* b */ | 2008 | if (!off) { |
| 1979 | last_itod_magic=ind; | 2009 | o(0xEA000000); /* b */ |
| 1980 | o(0x4F800000); /* 4294967296.0f */ | 2010 | last_itod_magic = ind; |
| 1981 | } | 2011 | o(0x4F800000); /* 4294967296.0f */ |
| 1982 | o(0xBE000100|dsize|(r2<<16)|(r2<<12)|r); /* adflt */ | 2012 | } |
| 1983 | } | 2013 | o(0xBE000100 | dsize | (r2 << 16) | (r2 << 12) | r); /* adflt */ |
| 2014 | } | ||
| 1984 | #endif | 2015 | #endif |
| 1985 | return; | 2016 | return; |
| 1986 | } else if(bt == VT_LLONG) { | 2017 | } else if (bt == VT_LLONG) { |
| 1987 | int func; | 2018 | int func; |
| 1988 | CType *func_type = 0; | 2019 | CType* func_type = 0; |
| 1989 | if((t & VT_BTYPE) == VT_FLOAT) { | 2020 | if ((t & VT_BTYPE) == VT_FLOAT) { |
| 1990 | func_type = &func_float_type; | 2021 | func_type = &func_float_type; |
| 1991 | if(vtop->type.t & VT_UNSIGNED) | 2022 | if (vtop->type.t & VT_UNSIGNED) |
| 1992 | func=TOK___floatundisf; | 2023 | func = TOK___floatundisf; |
| 1993 | else | 2024 | else |
| 1994 | func=TOK___floatdisf; | 2025 | func = TOK___floatdisf; |
| 1995 | #if LDOUBLE_SIZE != 8 | 2026 | #if LDOUBLE_SIZE != 8 |
| 1996 | } else if((t & VT_BTYPE) == VT_LDOUBLE) { | 2027 | } else if ((t & VT_BTYPE) == VT_LDOUBLE) { |
| 1997 | func_type = &func_ldouble_type; | 2028 | func_type = &func_ldouble_type; |
| 1998 | if(vtop->type.t & VT_UNSIGNED) | 2029 | if (vtop->type.t & VT_UNSIGNED) |
| 1999 | func=TOK___floatundixf; | 2030 | func = TOK___floatundixf; |
| 2000 | else | 2031 | else |
| 2001 | func=TOK___floatdixf; | 2032 | func = TOK___floatdixf; |
| 2002 | } else if((t & VT_BTYPE) == VT_DOUBLE) { | 2033 | } else if ((t & VT_BTYPE) == VT_DOUBLE) { |
| 2003 | #else | 2034 | #else |
| 2004 | } else if((t & VT_BTYPE) == VT_DOUBLE || (t & VT_BTYPE) == VT_LDOUBLE) { | 2035 | } else if ((t & VT_BTYPE) == VT_DOUBLE || |
| 2036 | (t & VT_BTYPE) == VT_LDOUBLE) { | ||
| 2005 | #endif | 2037 | #endif |
| 2006 | func_type = &func_double_type; | 2038 | func_type = &func_double_type; |
| 2007 | if(vtop->type.t & VT_UNSIGNED) | 2039 | if (vtop->type.t & VT_UNSIGNED) |
| 2008 | func=TOK___floatundidf; | 2040 | func = TOK___floatundidf; |
| 2009 | else | 2041 | else |
| 2010 | func=TOK___floatdidf; | 2042 | func = TOK___floatdidf; |
| 2011 | } | 2043 | } |
| 2012 | if(func_type) { | 2044 | if (func_type) { |
| 2013 | vpush_global_sym(func_type, func); | 2045 | vpush_global_sym(func_type, func); |
| 2014 | vswap(); | 2046 | vswap(); |
| 2015 | gfunc_call(1); | 2047 | gfunc_call(1); |
| 2016 | vpushi(0); | 2048 | vpushi(0); |
| 2017 | vtop->r=TREG_F0; | 2049 | vtop->r = TREG_F0; |
| 2018 | return; | 2050 | return; |
| 2051 | } | ||
| 2019 | } | 2052 | } |
| 2020 | } | 2053 | tcc_error("unimplemented gen_cvt_itof %x!", vtop->type.t); |
| 2021 | tcc_error("unimplemented gen_cvt_itof %x!",vtop->type.t); | ||
| 2022 | } | 2054 | } |
| 2023 | 2055 | ||
| 2024 | /* convert fp to int 't' type */ | 2056 | /* convert fp to int 't' type */ |
| 2025 | void gen_cvt_ftoi(int t) | 2057 | void gen_cvt_ftoi(int t) |
| 2026 | { | 2058 | { |
| 2027 | uint32_t r, r2; | 2059 | uint32_t r, r2; |
| 2028 | int u, func = 0; | 2060 | int u, func = 0; |
| 2029 | u=t&VT_UNSIGNED; | 2061 | u = t & VT_UNSIGNED; |
| 2030 | t&=VT_BTYPE; | 2062 | t &= VT_BTYPE; |
| 2031 | r2=vtop->type.t & VT_BTYPE; | 2063 | r2 = vtop->type.t & VT_BTYPE; |
| 2032 | if(t==VT_INT) { | 2064 | if (t == VT_INT) { |
| 2033 | #ifdef TCC_ARM_VFP | 2065 | #ifdef TCC_ARM_VFP |
| 2034 | r=vfpr(gv(RC_FLOAT)); | 2066 | r = vfpr(gv(RC_FLOAT)); |
| 2035 | u=u?0:0x10000; | 2067 | u = u ? 0 : 0x10000; |
| 2036 | o(0xEEBC0AC0|(r<<12)|r|T2CPR(r2)|u); /* ftoXizY */ | 2068 | o(0xEEBC0AC0 | (r << 12) | r | T2CPR(r2) | u); /* ftoXizY */ |
| 2037 | r2=intr(vtop->r=get_reg(RC_INT)); | 2069 | r2 = intr(vtop->r = get_reg(RC_INT)); |
| 2038 | o(0xEE100A10|(r<<16)|(r2<<12)); | 2070 | o(0xEE100A10 | (r << 16) | (r2 << 12)); |
| 2039 | return; | 2071 | return; |
| 2040 | #else | 2072 | #else |
| 2041 | if(u) { | 2073 | if (u) { |
| 2042 | if(r2 == VT_FLOAT) | 2074 | if (r2 == VT_FLOAT) |
| 2043 | func=TOK___fixunssfsi; | 2075 | func = TOK___fixunssfsi; |
| 2044 | #if LDOUBLE_SIZE != 8 | 2076 | #if LDOUBLE_SIZE != 8 |
| 2045 | else if(r2 == VT_LDOUBLE) | 2077 | else if (r2 == VT_LDOUBLE) |
| 2046 | func=TOK___fixunsxfsi; | 2078 | func = TOK___fixunsxfsi; |
| 2047 | else if(r2 == VT_DOUBLE) | 2079 | else if (r2 == VT_DOUBLE) |
| 2048 | #else | 2080 | #else |
| 2049 | else if(r2 == VT_LDOUBLE || r2 == VT_DOUBLE) | 2081 | else if (r2 == VT_LDOUBLE || r2 == VT_DOUBLE) |
| 2050 | #endif | 2082 | #endif |
| 2051 | func=TOK___fixunsdfsi; | 2083 | func = TOK___fixunsdfsi; |
| 2052 | } else { | 2084 | } else { |
| 2053 | r=fpr(gv(RC_FLOAT)); | 2085 | r = fpr(gv(RC_FLOAT)); |
| 2054 | r2=intr(vtop->r=get_reg(RC_INT)); | 2086 | r2 = intr(vtop->r = get_reg(RC_INT)); |
| 2055 | o(0xEE100170|(r2<<12)|r); | 2087 | o(0xEE100170 | (r2 << 12) | r); |
| 2056 | return; | 2088 | return; |
| 2057 | } | 2089 | } |
| 2058 | #endif | 2090 | #endif |
| 2059 | } else if(t == VT_LLONG) { // unsigned handled in gen_cvt_ftoi1 | 2091 | } else if (t == VT_LLONG) { // unsigned handled in gen_cvt_ftoi1 |
| 2060 | if(r2 == VT_FLOAT) | 2092 | if (r2 == VT_FLOAT) |
| 2061 | func=TOK___fixsfdi; | 2093 | func = TOK___fixsfdi; |
| 2062 | #if LDOUBLE_SIZE != 8 | 2094 | #if LDOUBLE_SIZE != 8 |
| 2063 | else if(r2 == VT_LDOUBLE) | 2095 | else if (r2 == VT_LDOUBLE) |
| 2064 | func=TOK___fixxfdi; | 2096 | func = TOK___fixxfdi; |
| 2065 | else if(r2 == VT_DOUBLE) | 2097 | else if (r2 == VT_DOUBLE) |
| 2066 | #else | 2098 | #else |
| 2067 | else if(r2 == VT_LDOUBLE || r2 == VT_DOUBLE) | 2099 | else if (r2 == VT_LDOUBLE || r2 == VT_DOUBLE) |
| 2068 | #endif | 2100 | #endif |
| 2069 | func=TOK___fixdfdi; | 2101 | func = TOK___fixdfdi; |
| 2070 | } | 2102 | } |
| 2071 | if(func) { | 2103 | if (func) { |
| 2072 | vpush_global_sym(&func_old_type, func); | 2104 | vpush_global_sym(&func_old_type, func); |
| 2073 | vswap(); | 2105 | vswap(); |
| 2074 | gfunc_call(1); | 2106 | gfunc_call(1); |
| 2075 | vpushi(0); | 2107 | vpushi(0); |
| 2076 | if(t == VT_LLONG) | 2108 | if (t == VT_LLONG) |
| 2077 | vtop->r2 = REG_LRET; | 2109 | vtop->r2 = REG_LRET; |
| 2078 | vtop->r = REG_IRET; | 2110 | vtop->r = REG_IRET; |
| 2079 | return; | 2111 | return; |
| 2080 | } | 2112 | } |
| 2081 | tcc_error("unimplemented gen_cvt_ftoi!"); | 2113 | tcc_error("unimplemented gen_cvt_ftoi!"); |
| 2082 | } | 2114 | } |
| 2083 | 2115 | ||
| 2084 | /* convert from one floating point type to another */ | 2116 | /* convert from one floating point type to another */ |
| 2085 | void gen_cvt_ftof(int t) | 2117 | void gen_cvt_ftof(int t) |
| 2086 | { | 2118 | { |
| 2087 | #ifdef TCC_ARM_VFP | 2119 | #ifdef TCC_ARM_VFP |
| 2088 | if(((vtop->type.t & VT_BTYPE) == VT_FLOAT) != ((t & VT_BTYPE) == VT_FLOAT)) { | 2120 | if (((vtop->type.t & VT_BTYPE) == VT_FLOAT) != |
| 2089 | uint32_t r = vfpr(gv(RC_FLOAT)); | 2121 | ((t & VT_BTYPE) == VT_FLOAT)) { |
| 2090 | o(0xEEB70AC0|(r<<12)|r|T2CPR(vtop->type.t)); | 2122 | uint32_t r = vfpr(gv(RC_FLOAT)); |
| 2091 | } | 2123 | o(0xEEB70AC0 | (r << 12) | r | T2CPR(vtop->type.t)); |
| 2124 | } | ||
| 2092 | #else | 2125 | #else |
| 2093 | /* all we have to do on i386 and FPA ARM is to put the float in a register */ | 2126 | /* all we have to do on i386 and FPA ARM is to put the float in a register |
| 2094 | gv(RC_FLOAT); | 2127 | */ |
| 2128 | gv(RC_FLOAT); | ||
| 2095 | #endif | 2129 | #endif |
| 2096 | } | 2130 | } |
| 2097 | 2131 | ||
| 2098 | /* computed goto support */ | 2132 | /* computed goto support */ |
| 2099 | void ggoto(void) | 2133 | void ggoto(void) |
| 2100 | { | 2134 | { |
| 2101 | gcall_or_jmp(1); | 2135 | gcall_or_jmp(1); |
| 2102 | vtop--; | 2136 | vtop--; |
| 2103 | } | 2137 | } |
| 2104 | 2138 | ||
| 2105 | /* Save the stack pointer onto the stack and return the location of its address */ | 2139 | /* Save the stack pointer onto the stack and return the location of its address |
| 2106 | ST_FUNC void gen_vla_sp_save(int addr) { | 2140 | */ |
| 2141 | ST_FUNC void gen_vla_sp_save(int addr) | ||
| 2142 | { | ||
| 2107 | tcc_error("variable length arrays unsupported for this target"); | 2143 | tcc_error("variable length arrays unsupported for this target"); |
| 2108 | } | 2144 | } |
| 2109 | 2145 | ||
| 2110 | /* Restore the SP from a location on the stack */ | 2146 | /* Restore the SP from a location on the stack */ |
| 2111 | ST_FUNC void gen_vla_sp_restore(int addr) { | 2147 | ST_FUNC void gen_vla_sp_restore(int addr) |
| 2148 | { | ||
| 2112 | tcc_error("variable length arrays unsupported for this target"); | 2149 | tcc_error("variable length arrays unsupported for this target"); |
| 2113 | } | 2150 | } |
| 2114 | 2151 | ||
| 2115 | /* Subtract from the stack pointer, and push the resulting value onto the stack */ | 2152 | /* Subtract from the stack pointer, and push the resulting value onto the stack |
| 2116 | ST_FUNC void gen_vla_alloc(CType *type, int align) { | 2153 | */ |
| 2154 | ST_FUNC void gen_vla_alloc(CType* type, int align) | ||
| 2155 | { | ||
| 2117 | tcc_error("variable length arrays unsupported for this target"); | 2156 | tcc_error("variable length arrays unsupported for this target"); |
| 2118 | } | 2157 | } |
| 2119 | 2158 | ||
| @@ -21,9 +21,9 @@ · 20 unmodified lines | |||
| 21 | 21 | ||
| 22 | #include "tcc.h" | 22 | #include "tcc.h" |
| 23 | 23 | ||
| 24 | #define MAXNSCNS 255 /* MAXIMUM NUMBER OF SECTIONS */ | 24 | #define MAXNSCNS 255 /* MAXIMUM NUMBER OF SECTIONS */ |
| 25 | #define MAX_STR_TABLE 1000000 | 25 | #define MAX_STR_TABLE 1000000 |
| 26 | AOUTHDR o_filehdr; /* OPTIONAL (A.OUT) FILE HEADER */ | 26 | AOUTHDR o_filehdr; /* OPTIONAL (A.OUT) FILE HEADER */ |
| 27 | 27 | ||
| 28 | SCNHDR section_header[MAXNSCNS]; | 28 | SCNHDR section_header[MAXNSCNS]; |
| 29 | 29 | ||
| @@ -38,14 +38,14 @@ int EndAddress[MAX_FUNCS]; · 8 unmodified lines | |||
| 38 | int LastLineNo[MAX_FUNCS]; | 38 | int LastLineNo[MAX_FUNCS]; |
| 39 | int FuncEntries[MAX_FUNCS]; | 39 | int FuncEntries[MAX_FUNCS]; |
| 40 | 40 | ||
| 41 | int OutputTheSection(Section * sect); | 41 | int OutputTheSection(Section* sect); |
| 42 | short int GetCoffFlags(const char *s); | 42 | short int GetCoffFlags(const char* s); |
| 43 | void SortSymbolTable(void); | 43 | void SortSymbolTable(void); |
| 44 | Section *FindSection(TCCState * s1, const char *sname); | 44 | Section* FindSection(TCCState* s1, const char* sname); |
| 45 | 45 | ||
| 46 | int C67_main_entry_point; | 46 | int C67_main_entry_point; |
| 47 | 47 | ||
| 48 | int FindCoffSymbolIndex(const char *func_name); | 48 | int FindCoffSymbolIndex(const char* func_name); |
| 49 | int nb_syms; | 49 | int nb_syms; |
| 50 | 50 | ||
| 51 | typedef struct { | 51 | typedef struct { |
| @@ -74,15 +74,15 @@ typedef struct { · 22 unmodified lines | |||
| 74 | unsigned short dummy4; | 74 | unsigned short dummy4; |
| 75 | } AUXEF; | 75 | } AUXEF; |
| 76 | 76 | ||
| 77 | ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f) | 77 | ST_FUNC int tcc_output_coff(TCCState* s1, FILE* f) |
| 78 | { | 78 | { |
| 79 | Section *tcc_sect; | 79 | Section* tcc_sect; |
| 80 | SCNHDR *coff_sec; | 80 | SCNHDR* coff_sec; |
| 81 | int file_pointer; | 81 | int file_pointer; |
| 82 | char *Coff_str_table, *pCoff_str_table; | 82 | char* Coff_str_table, *pCoff_str_table; |
| 83 | int CoffTextSectionNo, coff_nb_syms; | 83 | int CoffTextSectionNo, coff_nb_syms; |
| 84 | FILHDR file_hdr; /* FILE HEADER STRUCTURE */ | 84 | FILHDR file_hdr; /* FILE HEADER STRUCTURE */ |
| 85 | Section *stext, *sdata, *sbss; | 85 | Section* stext, *sdata, *sbss; |
| 86 | int i, NSectionsToOutput = 0; | 86 | int i, NSectionsToOutput = 0; |
| 87 | 87 | ||
| 88 | Coff_str_table = pCoff_str_table = NULL; | 88 | Coff_str_table = pCoff_str_table = NULL; |
| @@ -94,21 +94,21 @@ ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f) · 5 unmodified lines | |||
| 94 | nb_syms = symtab_section->data_offset / sizeof(Elf32_Sym); | 94 | nb_syms = symtab_section->data_offset / sizeof(Elf32_Sym); |
| 95 | coff_nb_syms = FindCoffSymbolIndex("XXXXXXXXXX1"); | 95 | coff_nb_syms = FindCoffSymbolIndex("XXXXXXXXXX1"); |
| 96 | 96 | ||
| 97 | file_hdr.f_magic = COFF_C67_MAGIC; /* magic number */ | 97 | file_hdr.f_magic = COFF_C67_MAGIC; /* magic number */ |
| 98 | file_hdr.f_timdat = 0; /* time & date stamp */ | 98 | file_hdr.f_timdat = 0; /* time & date stamp */ |
| 99 | file_hdr.f_opthdr = sizeof(AOUTHDR); /* sizeof(optional hdr) */ | 99 | file_hdr.f_opthdr = sizeof(AOUTHDR); /* sizeof(optional hdr) */ |
| 100 | file_hdr.f_flags = 0x1143; /* flags (copied from what code composer does) */ | 100 | file_hdr.f_flags = 0x1143; /* flags (copied from what code composer does) */ |
| 101 | file_hdr.f_TargetID = 0x99; /* for C6x = 0x0099 */ | 101 | file_hdr.f_TargetID = 0x99; /* for C6x = 0x0099 */ |
| 102 | 102 | ||
| 103 | o_filehdr.magic = 0x0108; /* see magic.h */ | 103 | o_filehdr.magic = 0x0108; /* see magic.h */ |
| 104 | o_filehdr.vstamp = 0x0190; /* version stamp */ | 104 | o_filehdr.vstamp = 0x0190; /* version stamp */ |
| 105 | o_filehdr.tsize = stext->data_offset; /* text size in bytes, padded to FW bdry */ | 105 | o_filehdr.tsize = |
| 106 | o_filehdr.dsize = sdata->data_offset; /* initialized data " " */ | 106 | stext->data_offset; /* text size in bytes, padded to FW bdry */ |
| 107 | o_filehdr.bsize = sbss->data_offset; /* uninitialized data " " */ | 107 | o_filehdr.dsize = sdata->data_offset; /* initialized data " " */ |
| 108 | o_filehdr.entrypt = C67_main_entry_point; /* entry pt. */ | 108 | o_filehdr.bsize = sbss->data_offset; /* uninitialized data " " */ |
| 109 | o_filehdr.text_start = stext->sh_addr; /* base of text used for this file */ | 109 | o_filehdr.entrypt = C67_main_entry_point; /* entry pt. */ |
| 110 | o_filehdr.data_start = sdata->sh_addr; /* base of data used for this file */ | 110 | o_filehdr.text_start = stext->sh_addr; /* base of text used for this file */ |
| 111 | 111 | o_filehdr.data_start = sdata->sh_addr; /* base of data used for this file */ | |
| 112 | 112 | ||
| 113 | // create all the section headers | 113 | // create all the section headers |
| 114 | 114 | ||
| @@ -117,831 +117,807 @@ ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f) · 2 unmodified lines | |||
| 117 | CoffTextSectionNo = -1; | 117 | CoffTextSectionNo = -1; |
| 118 | 118 | ||
| 119 | for (i = 1; i < s1->nb_sections; i++) { | 119 | for (i = 1; i < s1->nb_sections; i++) { |
| 120 | coff_sec = §ion_header[i]; | 120 | coff_sec = §ion_header[i]; |
| 121 | tcc_sect = s1->sections[i]; | 121 | tcc_sect = s1->sections[i]; |
| 122 | 122 | ||
| 123 | if (OutputTheSection(tcc_sect)) { | 123 | if (OutputTheSection(tcc_sect)) { |
| 124 | NSectionsToOutput++; | 124 | NSectionsToOutput++; |
| 125 | 125 | ||
| 126 | if (CoffTextSectionNo == -1 && tcc_sect == stext) | 126 | if (CoffTextSectionNo == -1 && tcc_sect == stext) |
| 127 | CoffTextSectionNo = NSectionsToOutput; // rem which coff sect number the .text sect is | 127 | CoffTextSectionNo = NSectionsToOutput; // rem which coff sect |
| 128 | 128 | // number the .text sect | |
| 129 | strcpy(coff_sec->s_name, tcc_sect->name); /* section name */ | 129 | // is |
| 130 | 130 | ||
| 131 | coff_sec->s_paddr = tcc_sect->sh_addr; /* physical address */ | 131 | strcpy(coff_sec->s_name, tcc_sect->name); /* section name */ |
| 132 | coff_sec->s_vaddr = tcc_sect->sh_addr; /* virtual address */ | 132 | |
| 133 | coff_sec->s_size = tcc_sect->data_offset; /* section size */ | 133 | coff_sec->s_paddr = tcc_sect->sh_addr; /* physical address */ |
| 134 | coff_sec->s_scnptr = 0; /* file ptr to raw data for section */ | 134 | coff_sec->s_vaddr = tcc_sect->sh_addr; /* virtual address */ |
| 135 | coff_sec->s_relptr = 0; /* file ptr to relocation */ | 135 | coff_sec->s_size = tcc_sect->data_offset; /* section size */ |
| 136 | coff_sec->s_lnnoptr = 0; /* file ptr to line numbers */ | 136 | coff_sec->s_scnptr = 0; /* file ptr to raw data for section */ |
| 137 | coff_sec->s_nreloc = 0; /* number of relocation entries */ | 137 | coff_sec->s_relptr = 0; /* file ptr to relocation */ |
| 138 | coff_sec->s_flags = GetCoffFlags(coff_sec->s_name); /* flags */ | 138 | coff_sec->s_lnnoptr = 0; /* file ptr to line numbers */ |
| 139 | coff_sec->s_reserved = 0; /* reserved byte */ | 139 | coff_sec->s_nreloc = 0; /* number of relocation entries */ |
| 140 | coff_sec->s_page = 0; /* memory page id */ | 140 | coff_sec->s_flags = GetCoffFlags(coff_sec->s_name); /* flags */ |
| 141 | 141 | coff_sec->s_reserved = 0; /* reserved byte */ | |
| 142 | file_pointer += sizeof(SCNHDR); | 142 | coff_sec->s_page = 0; /* memory page id */ |
| 143 | } | 143 | |
| 144 | file_pointer += sizeof(SCNHDR); | ||
| 145 | } | ||
| 144 | } | 146 | } |
| 145 | 147 | ||
| 146 | file_hdr.f_nscns = NSectionsToOutput; /* number of sections */ | 148 | file_hdr.f_nscns = NSectionsToOutput; /* number of sections */ |
| 147 | 149 | ||
| 148 | // now loop through and determine file pointer locations | 150 | // now loop through and determine file pointer locations |
| 149 | // for the raw data | 151 | // for the raw data |
| 150 | 152 | ||
| 151 | |||
| 152 | for (i = 1; i < s1->nb_sections; i++) { | 153 | for (i = 1; i < s1->nb_sections; i++) { |
| 153 | coff_sec = §ion_header[i]; | 154 | coff_sec = §ion_header[i]; |
| 154 | tcc_sect = s1->sections[i]; | 155 | tcc_sect = s1->sections[i]; |
| 155 | 156 | ||
| 156 | if (OutputTheSection(tcc_sect)) { | 157 | if (OutputTheSection(tcc_sect)) { |
| 157 | // put raw data | 158 | // put raw data |
| 158 | coff_sec->s_scnptr = file_pointer; /* file ptr to raw data for section */ | 159 | coff_sec->s_scnptr = |
| 159 | file_pointer += coff_sec->s_size; | 160 | file_pointer; /* file ptr to raw data for section */ |
| 160 | } | 161 | file_pointer += coff_sec->s_size; |
| 162 | } | ||
| 161 | } | 163 | } |
| 162 | 164 | ||
| 163 | // now loop through and determine file pointer locations | 165 | // now loop through and determine file pointer locations |
| 164 | // for the relocation data | 166 | // for the relocation data |
| 165 | 167 | ||
| 166 | for (i = 1; i < s1->nb_sections; i++) { | 168 | for (i = 1; i < s1->nb_sections; i++) { |
| 167 | coff_sec = §ion_header[i]; | 169 | coff_sec = §ion_header[i]; |
| 168 | tcc_sect = s1->sections[i]; | 170 | tcc_sect = s1->sections[i]; |
| 169 | 171 | ||
| 170 | if (OutputTheSection(tcc_sect)) { | 172 | if (OutputTheSection(tcc_sect)) { |
| 171 | // put relocations data | 173 | // put relocations data |
| 172 | if (coff_sec->s_nreloc > 0) { | 174 | if (coff_sec->s_nreloc > 0) { |
| 173 | coff_sec->s_relptr = file_pointer; /* file ptr to relocation */ | 175 | coff_sec->s_relptr = file_pointer; /* file ptr to relocation */ |
| 174 | file_pointer += coff_sec->s_nreloc * sizeof(struct reloc); | 176 | file_pointer += coff_sec->s_nreloc * sizeof(struct reloc); |
| 175 | } | 177 | } |
| 176 | } | 178 | } |
| 177 | } | 179 | } |
| 178 | 180 | ||
| 179 | // now loop through and determine file pointer locations | 181 | // now loop through and determine file pointer locations |
| 180 | // for the line number data | 182 | // for the line number data |
| 181 | 183 | ||
| 182 | for (i = 1; i < s1->nb_sections; i++) { | 184 | for (i = 1; i < s1->nb_sections; i++) { |
| 183 | coff_sec = §ion_header[i]; | 185 | coff_sec = §ion_header[i]; |
| 184 | tcc_sect = s1->sections[i]; | 186 | tcc_sect = s1->sections[i]; |
| 185 | 187 | ||
| 186 | coff_sec->s_nlnno = 0; | 188 | coff_sec->s_nlnno = 0; |
| 187 | coff_sec->s_lnnoptr = 0; | 189 | coff_sec->s_lnnoptr = 0; |
| 188 | 190 | ||
| 189 | if (s1->do_debug && tcc_sect == stext) { | 191 | if (s1->do_debug && tcc_sect == stext) { |
| 190 | // count how many line nos data | 192 | // count how many line nos data |
| 191 | 193 | ||
| 192 | // also find association between source file name and function | 194 | // also find association between source file name and function |
| 193 | // so we can sort the symbol table | 195 | // so we can sort the symbol table |
| 194 | 196 | ||
| 195 | 197 | Stab_Sym* sym, *sym_end; | |
| 196 | Stab_Sym *sym, *sym_end; | 198 | char func_name[MAX_FUNC_NAME_LENGTH], |
| 197 | char func_name[MAX_FUNC_NAME_LENGTH], | 199 | last_func_name[MAX_FUNC_NAME_LENGTH]; |
| 198 | last_func_name[MAX_FUNC_NAME_LENGTH]; | 200 | unsigned long func_addr, last_pc, pc; |
| 199 | unsigned long func_addr, last_pc, pc; | 201 | const char* incl_files[INCLUDE_STACK_SIZE]; |
| 200 | const char *incl_files[INCLUDE_STACK_SIZE]; | 202 | int incl_index, len, last_line_num; |
| 201 | int incl_index, len, last_line_num; | 203 | const char* str, *p; |
| 202 | const char *str, *p; | 204 | |
| 203 | 205 | coff_sec->s_lnnoptr = file_pointer; /* file ptr to linno */ | |
| 204 | coff_sec->s_lnnoptr = file_pointer; /* file ptr to linno */ | 206 | |
| 205 | 207 | func_name[0] = '\0'; | |
| 206 | 208 | func_addr = 0; | |
| 207 | func_name[0] = '\0'; | 209 | incl_index = 0; |
| 208 | func_addr = 0; | 210 | last_func_name[0] = '\0'; |
| 209 | incl_index = 0; | 211 | last_pc = 0xffffffff; |
| 210 | last_func_name[0] = '\0'; | 212 | last_line_num = 1; |
| 211 | last_pc = 0xffffffff; | 213 | sym = (Stab_Sym*)stab_section->data + 1; |
| 212 | last_line_num = 1; | 214 | sym_end = |
| 213 | sym = (Stab_Sym *) stab_section->data + 1; | 215 | (Stab_Sym*)(stab_section->data + stab_section->data_offset); |
| 214 | sym_end = | 216 | |
| 215 | (Stab_Sym *) (stab_section->data + | 217 | nFuncs = 0; |
| 216 | stab_section->data_offset); | 218 | while (sym < sym_end) { |
| 217 | 219 | switch (sym->n_type) { | |
| 218 | nFuncs = 0; | 220 | /* function start or end */ |
| 219 | while (sym < sym_end) { | 221 | case N_FUN: |
| 220 | switch (sym->n_type) { | 222 | if (sym->n_strx == 0) { |
| 221 | /* function start or end */ | 223 | // end of function |
| 222 | case N_FUN: | 224 | |
| 223 | if (sym->n_strx == 0) { | 225 | coff_sec->s_nlnno++; |
| 224 | // end of function | 226 | file_pointer += LINESZ; |
| 225 | 227 | ||
| 226 | coff_sec->s_nlnno++; | 228 | pc = sym->n_value + func_addr; |
| 227 | file_pointer += LINESZ; | 229 | func_name[0] = '\0'; |
| 228 | 230 | func_addr = 0; | |
| 229 | pc = sym->n_value + func_addr; | 231 | EndAddress[nFuncs] = pc; |
| 230 | func_name[0] = '\0'; | 232 | FuncEntries[nFuncs] = |
| 231 | func_addr = 0; | 233 | (file_pointer - LineNoFilePtr[nFuncs]) / LINESZ - 1; |
| 232 | EndAddress[nFuncs] = pc; | 234 | LastLineNo[nFuncs++] = last_line_num + 1; |
| 233 | FuncEntries[nFuncs] = | 235 | } else { |
| 234 | (file_pointer - | 236 | // beginning of function |
| 235 | LineNoFilePtr[nFuncs]) / LINESZ - 1; | 237 | |
| 236 | LastLineNo[nFuncs++] = last_line_num + 1; | 238 | LineNoFilePtr[nFuncs] = file_pointer; |
| 237 | } else { | 239 | coff_sec->s_nlnno++; |
| 238 | // beginning of function | 240 | file_pointer += LINESZ; |
| 239 | 241 | ||
| 240 | LineNoFilePtr[nFuncs] = file_pointer; | 242 | str = (const char*)stabstr_section->data + sym->n_strx; |
| 241 | coff_sec->s_nlnno++; | 243 | |
| 242 | file_pointer += LINESZ; | 244 | p = strchr(str, ':'); |
| 243 | 245 | if (!p) { | |
| 244 | str = | 246 | pstrcpy(func_name, sizeof(func_name), str); |
| 245 | (const char *) stabstr_section->data + | 247 | pstrcpy(Func[nFuncs], sizeof(func_name), str); |
| 246 | sym->n_strx; | 248 | } else { |
| 247 | 249 | len = p - str; | |
| 248 | p = strchr(str, ':'); | 250 | if (len > sizeof(func_name) - 1) |
| 249 | if (!p) { | 251 | len = sizeof(func_name) - 1; |
| 250 | pstrcpy(func_name, sizeof(func_name), str); | 252 | memcpy(func_name, str, len); |
| 251 | pstrcpy(Func[nFuncs], sizeof(func_name), str); | 253 | memcpy(Func[nFuncs], str, len); |
| 252 | } else { | 254 | func_name[len] = '\0'; |
| 253 | len = p - str; | 255 | } |
| 254 | if (len > sizeof(func_name) - 1) | 256 | |
| 255 | len = sizeof(func_name) - 1; | 257 | // save the file that it came in so we can sort later |
| 256 | memcpy(func_name, str, len); | 258 | pstrcpy(AssociatedFile[nFuncs], sizeof(func_name), |
| 257 | memcpy(Func[nFuncs], str, len); | 259 | incl_files[incl_index - 1]); |
| 258 | func_name[len] = '\0'; | 260 | |
| 259 | } | 261 | func_addr = sym->n_value; |
| 260 | 262 | } | |
| 261 | // save the file that it came in so we can sort later | 263 | break; |
| 262 | pstrcpy(AssociatedFile[nFuncs], sizeof(func_name), | 264 | |
| 263 | incl_files[incl_index - 1]); | 265 | /* line number info */ |
| 264 | 266 | case N_SLINE: | |
| 265 | func_addr = sym->n_value; | 267 | pc = sym->n_value + func_addr; |
| 266 | } | 268 | |
| 267 | break; | 269 | last_pc = pc; |
| 268 | 270 | last_line_num = sym->n_desc; | |
| 269 | /* line number info */ | 271 | |
| 270 | case N_SLINE: | 272 | /* XXX: slow! */ |
| 271 | pc = sym->n_value + func_addr; | 273 | strcpy(last_func_name, func_name); |
| 272 | 274 | ||
| 273 | last_pc = pc; | 275 | coff_sec->s_nlnno++; |
| 274 | last_line_num = sym->n_desc; | 276 | file_pointer += LINESZ; |
| 275 | 277 | break; | |
| 276 | /* XXX: slow! */ | 278 | /* include files */ |
| 277 | strcpy(last_func_name, func_name); | 279 | case N_BINCL: |
| 278 | 280 | str = (const char*)stabstr_section->data + sym->n_strx; | |
| 279 | coff_sec->s_nlnno++; | 281 | add_incl: |
| 280 | file_pointer += LINESZ; | 282 | if (incl_index < INCLUDE_STACK_SIZE) { |
| 281 | break; | 283 | incl_files[incl_index++] = str; |
| 282 | /* include files */ | 284 | } |
| 283 | case N_BINCL: | 285 | break; |
| 284 | str = | 286 | case N_EINCL: |
| 285 | (const char *) stabstr_section->data + sym->n_strx; | 287 | if (incl_index > 1) |
| 286 | add_incl: | 288 | incl_index--; |
| 287 | if (incl_index < INCLUDE_STACK_SIZE) { | 289 | break; |
| 288 | incl_files[incl_index++] = str; | 290 | case N_SO: |
| 289 | } | 291 | if (sym->n_strx == 0) { |
| 290 | break; | 292 | incl_index = 0; /* end of translation unit */ |
| 291 | case N_EINCL: | 293 | } else { |
| 292 | if (incl_index > 1) | 294 | str = (const char*)stabstr_section->data + sym->n_strx; |
| 293 | incl_index--; | 295 | /* do not add path */ |
| 294 | break; | 296 | len = strlen(str); |
| 295 | case N_SO: | 297 | if (len > 0 && str[len - 1] != '/') |
| 296 | if (sym->n_strx == 0) { | 298 | goto add_incl; |
| 297 | incl_index = 0; /* end of translation unit */ | 299 | } |
| 298 | } else { | 300 | break; |
| 299 | str = | 301 | } |
| 300 | (const char *) stabstr_section->data + | 302 | sym++; |
| 301 | sym->n_strx; | 303 | } |
| 302 | /* do not add path */ | 304 | } |
| 303 | len = strlen(str); | ||
| 304 | if (len > 0 && str[len - 1] != '/') | ||
| 305 | goto add_incl; | ||
| 306 | } | ||
| 307 | break; | ||
| 308 | } | ||
| 309 | sym++; | ||
| 310 | } | ||
| 311 | } | ||
| 312 | |||
| 313 | } | 305 | } |
| 314 | 306 | ||
| 315 | file_hdr.f_symptr = file_pointer; /* file pointer to symtab */ | 307 | file_hdr.f_symptr = file_pointer; /* file pointer to symtab */ |
| 316 | 308 | ||
| 317 | if (s1->do_debug) | 309 | if (s1->do_debug) |
| 318 | file_hdr.f_nsyms = coff_nb_syms; /* number of symtab entries */ | 310 | file_hdr.f_nsyms = coff_nb_syms; /* number of symtab entries */ |
| 319 | else | 311 | else |
| 320 | file_hdr.f_nsyms = 0; | 312 | file_hdr.f_nsyms = 0; |
| 321 | 313 | ||
| 322 | file_pointer += file_hdr.f_nsyms * SYMNMLEN; | 314 | file_pointer += file_hdr.f_nsyms * SYMNMLEN; |
| 323 | 315 | ||
| 324 | // OK now we are all set to write the file | 316 | // OK now we are all set to write the file |
| 325 | 317 | ||
| 326 | |||
| 327 | fwrite(&file_hdr, FILHSZ, 1, f); | 318 | fwrite(&file_hdr, FILHSZ, 1, f); |
| 328 | fwrite(&o_filehdr, sizeof(o_filehdr), 1, f); | 319 | fwrite(&o_filehdr, sizeof(o_filehdr), 1, f); |
| 329 | 320 | ||
| 330 | // write section headers | 321 | // write section headers |
| 331 | for (i = 1; i < s1->nb_sections; i++) { | 322 | for (i = 1; i < s1->nb_sections; i++) { |
| 332 | coff_sec = §ion_header[i]; | 323 | coff_sec = §ion_header[i]; |
| 333 | tcc_sect = s1->sections[i]; | 324 | tcc_sect = s1->sections[i]; |
| 334 | 325 | ||
| 335 | if (OutputTheSection(tcc_sect)) { | 326 | if (OutputTheSection(tcc_sect)) { |
| 336 | fwrite(coff_sec, sizeof(SCNHDR), 1, f); | 327 | fwrite(coff_sec, sizeof(SCNHDR), 1, f); |
| 337 | } | 328 | } |
| 338 | } | 329 | } |
| 339 | 330 | ||
| 340 | // write raw data | 331 | // write raw data |
| 341 | for (i = 1; i < s1->nb_sections; i++) { | 332 | for (i = 1; i < s1->nb_sections; i++) { |
| 342 | coff_sec = §ion_header[i]; | 333 | coff_sec = §ion_header[i]; |
| 343 | tcc_sect = s1->sections[i]; | 334 | tcc_sect = s1->sections[i]; |
| 344 | 335 | ||
| 345 | if (OutputTheSection(tcc_sect)) { | 336 | if (OutputTheSection(tcc_sect)) { |
| 346 | fwrite(tcc_sect->data, tcc_sect->data_offset, 1, f); | 337 | fwrite(tcc_sect->data, tcc_sect->data_offset, 1, f); |
| 347 | } | 338 | } |
| 348 | } | 339 | } |
| 349 | 340 | ||
| 350 | // write relocation data | 341 | // write relocation data |
| 351 | for (i = 1; i < s1->nb_sections; i++) { | 342 | for (i = 1; i < s1->nb_sections; i++) { |
| 352 | coff_sec = §ion_header[i]; | 343 | coff_sec = §ion_header[i]; |
| 353 | tcc_sect = s1->sections[i]; | 344 | tcc_sect = s1->sections[i]; |
| 354 | 345 | ||
| 355 | if (OutputTheSection(tcc_sect)) { | 346 | if (OutputTheSection(tcc_sect)) { |
| 356 | // put relocations data | 347 | // put relocations data |
| 357 | if (coff_sec->s_nreloc > 0) { | 348 | if (coff_sec->s_nreloc > 0) { |
| 358 | fwrite(tcc_sect->reloc, | 349 | fwrite(tcc_sect->reloc, |
| 359 | coff_sec->s_nreloc * sizeof(struct reloc), 1, f); | 350 | coff_sec->s_nreloc * sizeof(struct reloc), 1, f); |
| 360 | } | 351 | } |
| 361 | } | 352 | } |
| 362 | } | 353 | } |
| 363 | 354 | ||
| 364 | |||
| 365 | // group the symbols in order of filename, func1, func2, etc | 355 | // group the symbols in order of filename, func1, func2, etc |
| 366 | // finally global symbols | 356 | // finally global symbols |
| 367 | 357 | ||
| 368 | if (s1->do_debug) | 358 | if (s1->do_debug) |
| 369 | SortSymbolTable(); | 359 | SortSymbolTable(); |
| 370 | 360 | ||
| 371 | // write line no data | 361 | // write line no data |
| 372 | 362 | ||
| 373 | for (i = 1; i < s1->nb_sections; i++) { | 363 | for (i = 1; i < s1->nb_sections; i++) { |
| 374 | coff_sec = §ion_header[i]; | 364 | coff_sec = §ion_header[i]; |
| 375 | tcc_sect = s1->sections[i]; | 365 | tcc_sect = s1->sections[i]; |
| 376 | 366 | ||
| 377 | if (s1->do_debug && tcc_sect == stext) { | 367 | if (s1->do_debug && tcc_sect == stext) { |
| 378 | // count how many line nos data | 368 | // count how many line nos data |
| 379 | 369 | ||
| 380 | 370 | Stab_Sym* sym, *sym_end; | |
| 381 | Stab_Sym *sym, *sym_end; | 371 | char func_name[128], last_func_name[128]; |
| 382 | char func_name[128], last_func_name[128]; | 372 | unsigned long func_addr, last_pc, pc; |
| 383 | unsigned long func_addr, last_pc, pc; | 373 | const char* incl_files[INCLUDE_STACK_SIZE]; |
| 384 | const char *incl_files[INCLUDE_STACK_SIZE]; | 374 | int incl_index, len, last_line_num; |
| 385 | int incl_index, len, last_line_num; | 375 | const char* str, *p; |
| 386 | const char *str, *p; | 376 | |
| 387 | 377 | LINENO CoffLineNo; | |
| 388 | LINENO CoffLineNo; | 378 | |
| 389 | 379 | func_name[0] = '\0'; | |
| 390 | func_name[0] = '\0'; | 380 | func_addr = 0; |
| 391 | func_addr = 0; | 381 | incl_index = 0; |
| 392 | incl_index = 0; | 382 | last_func_name[0] = '\0'; |
| 393 | last_func_name[0] = '\0'; | 383 | last_pc = 0; |
| 394 | last_pc = 0; | 384 | last_line_num = 1; |
| 395 | last_line_num = 1; | 385 | sym = (Stab_Sym*)stab_section->data + 1; |
| 396 | sym = (Stab_Sym *) stab_section->data + 1; | 386 | sym_end = |
| 397 | sym_end = | 387 | (Stab_Sym*)(stab_section->data + stab_section->data_offset); |
| 398 | (Stab_Sym *) (stab_section->data + | 388 | |
| 399 | stab_section->data_offset); | 389 | while (sym < sym_end) { |
| 400 | 390 | switch (sym->n_type) { | |
| 401 | while (sym < sym_end) { | 391 | /* function start or end */ |
| 402 | switch (sym->n_type) { | 392 | case N_FUN: |
| 403 | /* function start or end */ | 393 | if (sym->n_strx == 0) { |
| 404 | case N_FUN: | 394 | // end of function |
| 405 | if (sym->n_strx == 0) { | 395 | |
| 406 | // end of function | 396 | CoffLineNo.l_addr.l_paddr = last_pc; |
| 407 | 397 | CoffLineNo.l_lnno = last_line_num + 1; | |
| 408 | CoffLineNo.l_addr.l_paddr = last_pc; | 398 | fwrite(&CoffLineNo, 6, 1, f); |
| 409 | CoffLineNo.l_lnno = last_line_num + 1; | 399 | |
| 410 | fwrite(&CoffLineNo, 6, 1, f); | 400 | pc = sym->n_value + func_addr; |
| 411 | 401 | func_name[0] = '\0'; | |
| 412 | pc = sym->n_value + func_addr; | 402 | func_addr = 0; |
| 413 | func_name[0] = '\0'; | 403 | } else { |
| 414 | func_addr = 0; | 404 | // beginning of function |
| 415 | } else { | 405 | |
| 416 | // beginning of function | 406 | str = (const char*)stabstr_section->data + sym->n_strx; |
| 417 | 407 | ||
| 418 | str = | 408 | p = strchr(str, ':'); |
| 419 | (const char *) stabstr_section->data + | 409 | if (!p) { |
| 420 | sym->n_strx; | 410 | pstrcpy(func_name, sizeof(func_name), str); |
| 421 | 411 | } else { | |
| 422 | 412 | len = p - str; | |
| 423 | p = strchr(str, ':'); | 413 | if (len > sizeof(func_name) - 1) |
| 424 | if (!p) { | 414 | len = sizeof(func_name) - 1; |
| 425 | pstrcpy(func_name, sizeof(func_name), str); | 415 | memcpy(func_name, str, len); |
| 426 | } else { | 416 | func_name[len] = '\0'; |
| 427 | len = p - str; | 417 | } |
| 428 | if (len > sizeof(func_name) - 1) | 418 | func_addr = sym->n_value; |
| 429 | len = sizeof(func_name) - 1; | 419 | last_pc = func_addr; |
| 430 | memcpy(func_name, str, len); | 420 | last_line_num = -1; |
| 431 | func_name[len] = '\0'; | 421 | |
| 432 | } | 422 | // output a function begin |
| 433 | func_addr = sym->n_value; | 423 | |
| 434 | last_pc = func_addr; | 424 | CoffLineNo.l_addr.l_symndx = |
| 435 | last_line_num = -1; | 425 | FindCoffSymbolIndex(func_name); |
| 436 | 426 | CoffLineNo.l_lnno = 0; | |
| 437 | // output a function begin | 427 | |
| 438 | 428 | fwrite(&CoffLineNo, 6, 1, f); | |
| 439 | CoffLineNo.l_addr.l_symndx = | 429 | } |
| 440 | FindCoffSymbolIndex(func_name); | 430 | break; |
| 441 | CoffLineNo.l_lnno = 0; | 431 | |
| 442 | 432 | /* line number info */ | |
| 443 | fwrite(&CoffLineNo, 6, 1, f); | 433 | case N_SLINE: |
| 444 | } | 434 | pc = sym->n_value + func_addr; |
| 445 | break; | 435 | |
| 446 | 436 | /* XXX: slow! */ | |
| 447 | /* line number info */ | 437 | strcpy(last_func_name, func_name); |
| 448 | case N_SLINE: | 438 | |
| 449 | pc = sym->n_value + func_addr; | 439 | // output a line reference |
| 450 | 440 | ||
| 451 | 441 | CoffLineNo.l_addr.l_paddr = last_pc; | |
| 452 | /* XXX: slow! */ | 442 | |
| 453 | strcpy(last_func_name, func_name); | 443 | if (last_line_num == -1) { |
| 454 | 444 | CoffLineNo.l_lnno = sym->n_desc; | |
| 455 | // output a line reference | 445 | } else { |
| 456 | 446 | CoffLineNo.l_lnno = last_line_num + 1; | |
| 457 | CoffLineNo.l_addr.l_paddr = last_pc; | 447 | } |
| 458 | 448 | ||
| 459 | if (last_line_num == -1) { | 449 | fwrite(&CoffLineNo, 6, 1, f); |
| 460 | CoffLineNo.l_lnno = sym->n_desc; | 450 | |
| 461 | } else { | 451 | last_pc = pc; |
| 462 | CoffLineNo.l_lnno = last_line_num + 1; | 452 | last_line_num = sym->n_desc; |
| 463 | } | 453 | |
| 464 | 454 | break; | |
| 465 | fwrite(&CoffLineNo, 6, 1, f); | 455 | |
| 466 | 456 | /* include files */ | |
| 467 | last_pc = pc; | 457 | case N_BINCL: |
| 468 | last_line_num = sym->n_desc; | 458 | str = (const char*)stabstr_section->data + sym->n_strx; |
| 469 | 459 | add_incl2: | |
| 470 | break; | 460 | if (incl_index < INCLUDE_STACK_SIZE) { |
| 471 | 461 | incl_files[incl_index++] = str; | |
| 472 | /* include files */ | 462 | } |
| 473 | case N_BINCL: | 463 | break; |
| 474 | str = | 464 | case N_EINCL: |
| 475 | (const char *) stabstr_section->data + sym->n_strx; | 465 | if (incl_index > 1) |
| 476 | add_incl2: | 466 | incl_index--; |
| 477 | if (incl_index < INCLUDE_STACK_SIZE) { | 467 | break; |
| 478 | incl_files[incl_index++] = str; | 468 | case N_SO: |
| 479 | } | 469 | if (sym->n_strx == 0) { |
| 480 | break; | 470 | incl_index = 0; /* end of translation unit */ |
| 481 | case N_EINCL: | 471 | } else { |
| 482 | if (incl_index > 1) | 472 | str = (const char*)stabstr_section->data + sym->n_strx; |
| 483 | incl_index--; | 473 | /* do not add path */ |
| 484 | break; | 474 | len = strlen(str); |
| 485 | case N_SO: | 475 | if (len > 0 && str[len - 1] != '/') |
| 486 | if (sym->n_strx == 0) { | 476 | goto add_incl2; |
| 487 | incl_index = 0; /* end of translation unit */ | 477 | } |
| 488 | } else { | 478 | break; |
| 489 | str = | 479 | } |
| 490 | (const char *) stabstr_section->data + | 480 | sym++; |
| 491 | sym->n_strx; | 481 | } |
| 492 | /* do not add path */ | 482 | } |
| 493 | len = strlen(str); | ||
| 494 | if (len > 0 && str[len - 1] != '/') | ||
| 495 | goto add_incl2; | ||
| 496 | } | ||
| 497 | break; | ||
| 498 | } | ||
| 499 | sym++; | ||
| 500 | } | ||
| 501 | } | ||
| 502 | } | 483 | } |
| 503 | 484 | ||
| 504 | // write symbol table | 485 | // write symbol table |
| 505 | if (s1->do_debug) { | 486 | if (s1->do_debug) { |
| 506 | int k; | 487 | int k; |
| 507 | struct syment csym; | 488 | struct syment csym; |
| 508 | AUXFUNC auxfunc; | 489 | AUXFUNC auxfunc; |
| 509 | AUXBF auxbf; | 490 | AUXBF auxbf; |
| 510 | AUXEF auxef; | 491 | AUXEF auxef; |
| 511 | int i; | 492 | int i; |
| 512 | Elf32_Sym *p; | 493 | Elf32_Sym* p; |
| 513 | const char *name; | 494 | const char* name; |
| 514 | int nstr; | 495 | int nstr; |
| 515 | int n = 0; | 496 | int n = 0; |
| 516 | 497 | ||
| 517 | Coff_str_table = (char *) tcc_malloc(MAX_STR_TABLE); | 498 | Coff_str_table = (char*)tcc_malloc(MAX_STR_TABLE); |
| 518 | pCoff_str_table = Coff_str_table; | 499 | pCoff_str_table = Coff_str_table; |
| 519 | nstr = 0; | 500 | nstr = 0; |
| 520 | 501 | ||
| 521 | p = (Elf32_Sym *) symtab_section->data; | 502 | p = (Elf32_Sym*)symtab_section->data; |
| 522 | 503 | ||
| 523 | 504 | for (i = 0; i < nb_syms; i++) { | |
| 524 | for (i = 0; i < nb_syms; i++) { | 505 | |
| 525 | 506 | name = symtab_section->link->data + p->st_name; | |
| 526 | name = symtab_section->link->data + p->st_name; | 507 | |
| 527 | 508 | for (k = 0; k < 8; k++) | |
| 528 | for (k = 0; k < 8; k++) | 509 | csym._n._n_name[k] = 0; |
| 529 | csym._n._n_name[k] = 0; | 510 | |
| 530 | 511 | if (strlen(name) <= 8) { | |
| 531 | if (strlen(name) <= 8) { | 512 | strcpy(csym._n._n_name, name); |
| 532 | strcpy(csym._n._n_name, name); | 513 | } else { |
| 533 | } else { | 514 | if (pCoff_str_table - Coff_str_table + strlen(name) > |
| 534 | if (pCoff_str_table - Coff_str_table + strlen(name) > | 515 | MAX_STR_TABLE - 1) |
| 535 | MAX_STR_TABLE - 1) | 516 | tcc_error("String table too large"); |
| 536 | tcc_error("String table too large"); | 517 | |
| 537 | 518 | csym._n._n_n._n_zeroes = 0; | |
| 538 | csym._n._n_n._n_zeroes = 0; | 519 | csym._n._n_n._n_offset = pCoff_str_table - Coff_str_table + 4; |
| 539 | csym._n._n_n._n_offset = | 520 | |
| 540 | pCoff_str_table - Coff_str_table + 4; | 521 | strcpy(pCoff_str_table, name); |
| 541 | 522 | pCoff_str_table += strlen(name) + 1; // skip over null | |
| 542 | strcpy(pCoff_str_table, name); | 523 | nstr++; |
| 543 | pCoff_str_table += strlen(name) + 1; // skip over null | 524 | } |
| 544 | nstr++; | 525 | |
| 545 | } | 526 | if (p->st_info == 4) { |
| 546 | 527 | // put a filename symbol | |
| 547 | if (p->st_info == 4) { | 528 | csym.n_value = 33; // ????? |
| 548 | // put a filename symbol | 529 | csym.n_scnum = N_DEBUG; |
| 549 | csym.n_value = 33; // ????? | 530 | csym.n_type = 0; |
| 550 | csym.n_scnum = N_DEBUG; | 531 | csym.n_sclass = C_FILE; |
| 551 | csym.n_type = 0; | 532 | csym.n_numaux = 0; |
| 552 | csym.n_sclass = C_FILE; | 533 | fwrite(&csym, 18, 1, f); |
| 553 | csym.n_numaux = 0; | 534 | n++; |
| 554 | fwrite(&csym, 18, 1, f); | 535 | |
| 555 | n++; | 536 | } else if (p->st_info == 0x12) { |
| 556 | 537 | // find the function data | |
| 557 | } else if (p->st_info == 0x12) { | 538 | |
| 558 | // find the function data | 539 | for (k = 0; k < nFuncs; k++) { |
| 559 | 540 | if (strcmp(name, Func[k]) == 0) | |
| 560 | for (k = 0; k < nFuncs; k++) { | 541 | break; |
| 561 | if (strcmp(name, Func[k]) == 0) | 542 | } |
| 562 | break; | 543 | |
| 563 | } | 544 | if (k >= nFuncs) { |
| 564 | 545 | tcc_error("debug info can't find function: %s", name); | |
| 565 | if (k >= nFuncs) { | 546 | } |
| 566 | tcc_error("debug info can't find function: %s", name); | 547 | // put a Function Name |
| 567 | } | 548 | |
| 568 | // put a Function Name | 549 | csym.n_value = p->st_value; // physical address |
| 569 | 550 | csym.n_scnum = CoffTextSectionNo; | |
| 570 | csym.n_value = p->st_value; // physical address | 551 | csym.n_type = MKTYPE(T_INT, DT_FCN, 0, 0, 0, 0, 0); |
| 571 | csym.n_scnum = CoffTextSectionNo; | 552 | csym.n_sclass = C_EXT; |
| 572 | csym.n_type = MKTYPE(T_INT, DT_FCN, 0, 0, 0, 0, 0); | 553 | csym.n_numaux = 1; |
| 573 | csym.n_sclass = C_EXT; | 554 | fwrite(&csym, 18, 1, f); |
| 574 | csym.n_numaux = 1; | 555 | |
| 575 | fwrite(&csym, 18, 1, f); | 556 | // now put aux info |
| 576 | 557 | ||
| 577 | // now put aux info | 558 | auxfunc.tag = 0; |
| 578 | 559 | auxfunc.size = EndAddress[k] - p->st_value; | |
| 579 | auxfunc.tag = 0; | 560 | auxfunc.fileptr = LineNoFilePtr[k]; |
| 580 | auxfunc.size = EndAddress[k] - p->st_value; | 561 | auxfunc.nextsym = n + 6; // tktk |
| 581 | auxfunc.fileptr = LineNoFilePtr[k]; | 562 | auxfunc.dummy = 0; |
| 582 | auxfunc.nextsym = n + 6; // tktk | 563 | fwrite(&auxfunc, 18, 1, f); |
| 583 | auxfunc.dummy = 0; | 564 | |
| 584 | fwrite(&auxfunc, 18, 1, f); | 565 | // put a .bf |
| 585 | 566 | ||
| 586 | // put a .bf | 567 | strcpy(csym._n._n_name, ".bf"); |
| 587 | 568 | csym.n_value = p->st_value; // physical address | |
| 588 | strcpy(csym._n._n_name, ".bf"); | 569 | csym.n_scnum = CoffTextSectionNo; |
| 589 | csym.n_value = p->st_value; // physical address | 570 | csym.n_type = 0; |
| 590 | csym.n_scnum = CoffTextSectionNo; | 571 | csym.n_sclass = C_FCN; |
| 591 | csym.n_type = 0; | 572 | csym.n_numaux = 1; |
| 592 | csym.n_sclass = C_FCN; | 573 | fwrite(&csym, 18, 1, f); |
| 593 | csym.n_numaux = 1; | 574 | |
| 594 | fwrite(&csym, 18, 1, f); | 575 | // now put aux info |
| 595 | 576 | ||
| 596 | // now put aux info | 577 | auxbf.regmask = 0; |
| 597 | 578 | auxbf.lineno = 0; | |
| 598 | auxbf.regmask = 0; | 579 | auxbf.nentries = FuncEntries[k]; |
| 599 | auxbf.lineno = 0; | 580 | auxbf.localframe = 0; |
| 600 | auxbf.nentries = FuncEntries[k]; | 581 | auxbf.nextentry = n + 6; |
| 601 | auxbf.localframe = 0; | 582 | auxbf.dummy = 0; |
| 602 | auxbf.nextentry = n + 6; | 583 | fwrite(&auxbf, 18, 1, f); |
| 603 | auxbf.dummy = 0; | 584 | |
| 604 | fwrite(&auxbf, 18, 1, f); | 585 | // put a .ef |
| 605 | 586 | ||
| 606 | // put a .ef | 587 | strcpy(csym._n._n_name, ".ef"); |
| 607 | 588 | csym.n_value = EndAddress[k]; // physical address | |
| 608 | strcpy(csym._n._n_name, ".ef"); | 589 | csym.n_scnum = CoffTextSectionNo; |
| 609 | csym.n_value = EndAddress[k]; // physical address | 590 | csym.n_type = 0; |
| 610 | csym.n_scnum = CoffTextSectionNo; | 591 | csym.n_sclass = C_FCN; |
| 611 | csym.n_type = 0; | 592 | csym.n_numaux = 1; |
| 612 | csym.n_sclass = C_FCN; | 593 | fwrite(&csym, 18, 1, f); |
| 613 | csym.n_numaux = 1; | 594 | |
| 614 | fwrite(&csym, 18, 1, f); | 595 | // now put aux info |
| 615 | 596 | ||
| 616 | // now put aux info | 597 | auxef.dummy = 0; |
| 617 | 598 | auxef.lineno = LastLineNo[k]; | |
| 618 | auxef.dummy = 0; | 599 | auxef.dummy1 = 0; |
| 619 | auxef.lineno = LastLineNo[k]; | 600 | auxef.dummy2 = 0; |
| 620 | auxef.dummy1 = 0; | 601 | auxef.dummy3 = 0; |
| 621 | auxef.dummy2 = 0; | 602 | auxef.dummy4 = 0; |
| 622 | auxef.dummy3 = 0; | 603 | fwrite(&auxef, 18, 1, f); |
| 623 | auxef.dummy4 = 0; | 604 | |
| 624 | fwrite(&auxef, 18, 1, f); | 605 | n += 6; |
| 625 | 606 | ||
| 626 | n += 6; | 607 | } else { |
| 627 | 608 | // try an put some type info | |
| 628 | } else { | 609 | |
| 629 | // try an put some type info | 610 | if ((p->st_other & VT_BTYPE) == VT_DOUBLE) { |
| 630 | 611 | csym.n_type = T_DOUBLE; // int | |
| 631 | if ((p->st_other & VT_BTYPE) == VT_DOUBLE) { | 612 | csym.n_sclass = C_EXT; |
| 632 | csym.n_type = T_DOUBLE; // int | 613 | } else if ((p->st_other & VT_BTYPE) == VT_FLOAT) { |
| 633 | csym.n_sclass = C_EXT; | 614 | csym.n_type = T_FLOAT; |
| 634 | } else if ((p->st_other & VT_BTYPE) == VT_FLOAT) { | 615 | csym.n_sclass = C_EXT; |
| 635 | csym.n_type = T_FLOAT; | 616 | } else if ((p->st_other & VT_BTYPE) == VT_INT) { |
| 636 | csym.n_sclass = C_EXT; | 617 | csym.n_type = T_INT; // int |
| 637 | } else if ((p->st_other & VT_BTYPE) == VT_INT) { | 618 | csym.n_sclass = C_EXT; |
| 638 | csym.n_type = T_INT; // int | 619 | } else if ((p->st_other & VT_BTYPE) == VT_SHORT) { |
| 639 | csym.n_sclass = C_EXT; | 620 | csym.n_type = T_SHORT; |
| 640 | } else if ((p->st_other & VT_BTYPE) == VT_SHORT) { | 621 | csym.n_sclass = C_EXT; |
| 641 | csym.n_type = T_SHORT; | 622 | } else if ((p->st_other & VT_BTYPE) == VT_BYTE) { |
| 642 | csym.n_sclass = C_EXT; | 623 | csym.n_type = T_CHAR; |
| 643 | } else if ((p->st_other & VT_BTYPE) == VT_BYTE) { | 624 | csym.n_sclass = C_EXT; |
| 644 | csym.n_type = T_CHAR; | 625 | } else { |
| 645 | csym.n_sclass = C_EXT; | 626 | csym.n_type = T_INT; // just mark as a label |
| 646 | } else { | 627 | csym.n_sclass = C_LABEL; |
| 647 | csym.n_type = T_INT; // just mark as a label | 628 | } |
| 648 | csym.n_sclass = C_LABEL; | 629 | |
| 649 | } | 630 | csym.n_value = p->st_value; |
| 650 | 631 | csym.n_scnum = 2; | |
| 651 | 632 | csym.n_numaux = 1; | |
| 652 | csym.n_value = p->st_value; | 633 | fwrite(&csym, 18, 1, f); |
| 653 | csym.n_scnum = 2; | 634 | |
| 654 | csym.n_numaux = 1; | 635 | auxfunc.tag = 0; |
| 655 | fwrite(&csym, 18, 1, f); | 636 | auxfunc.size = 0x20; |
| 656 | 637 | auxfunc.fileptr = 0; | |
| 657 | auxfunc.tag = 0; | 638 | auxfunc.nextsym = 0; |
| 658 | auxfunc.size = 0x20; | 639 | auxfunc.dummy = 0; |
| 659 | auxfunc.fileptr = 0; | 640 | fwrite(&auxfunc, 18, 1, f); |
| 660 | auxfunc.nextsym = 0; | 641 | n++; |
| 661 | auxfunc.dummy = 0; | 642 | n++; |
| 662 | fwrite(&auxfunc, 18, 1, f); | 643 | } |
| 663 | n++; | 644 | |
| 664 | n++; | 645 | p++; |
| 665 | 646 | } | |
| 666 | } | ||
| 667 | |||
| 668 | p++; | ||
| 669 | } | ||
| 670 | } | 647 | } |
| 671 | 648 | ||
| 672 | if (s1->do_debug) { | 649 | if (s1->do_debug) { |
| 673 | // write string table | 650 | // write string table |
| 674 | 651 | ||
| 675 | // first write the size | 652 | // first write the size |
| 676 | i = pCoff_str_table - Coff_str_table; | 653 | i = pCoff_str_table - Coff_str_table; |
| 677 | fwrite(&i, 4, 1, f); | 654 | fwrite(&i, 4, 1, f); |
| 678 | 655 | ||
| 679 | // then write the strings | 656 | // then write the strings |
| 680 | fwrite(Coff_str_table, i, 1, f); | 657 | fwrite(Coff_str_table, i, 1, f); |
| 681 | 658 | ||
| 682 | tcc_free(Coff_str_table); | 659 | tcc_free(Coff_str_table); |
| 683 | } | 660 | } |
| 684 | 661 | ||
| 685 | return 0; | 662 | return 0; |
| 686 | } | 663 | } |
| 687 | 664 | ||
| 688 | |||
| 689 | |||
| 690 | // group the symbols in order of filename, func1, func2, etc | 665 | // group the symbols in order of filename, func1, func2, etc |
| 691 | // finally global symbols | 666 | // finally global symbols |
| 692 | 667 | ||
| 693 | void SortSymbolTable(void) | 668 | void SortSymbolTable(void) |
| 694 | { | 669 | { |
| 695 | int i, j, k, n = 0; | 670 | int i, j, k, n = 0; |
| 696 | Elf32_Sym *p, *p2, *NewTable; | 671 | Elf32_Sym* p, *p2, *NewTable; |
| 697 | char *name, *name2; | 672 | char* name, *name2; |
| 698 | |||
| 699 | NewTable = (Elf32_Sym *) tcc_malloc(nb_syms * sizeof(Elf32_Sym)); | ||
| 700 | 673 | ||
| 701 | p = (Elf32_Sym *) symtab_section->data; | 674 | NewTable = (Elf32_Sym*)tcc_malloc(nb_syms * sizeof(Elf32_Sym)); |
| 702 | 675 | ||
| 676 | p = (Elf32_Sym*)symtab_section->data; | ||
| 703 | 677 | ||
| 704 | // find a file symbol, copy it over | 678 | // find a file symbol, copy it over |
| 705 | // then scan the whole symbol list and copy any function | 679 | // then scan the whole symbol list and copy any function |
| 706 | // symbols that match the file association | 680 | // symbols that match the file association |
| 707 | 681 | ||
| 708 | for (i = 0; i < nb_syms; i++) { | 682 | for (i = 0; i < nb_syms; i++) { |
| 709 | if (p->st_info == 4) { | 683 | if (p->st_info == 4) { |
| 710 | name = (char *) symtab_section->link->data + p->st_name; | 684 | name = (char*)symtab_section->link->data + p->st_name; |
| 711 | 685 | ||
| 712 | // this is a file symbol, copy it over | 686 | // this is a file symbol, copy it over |
| 713 | 687 | ||
| 714 | NewTable[n++] = *p; | 688 | NewTable[n++] = *p; |
| 715 | 689 | ||
| 716 | p2 = (Elf32_Sym *) symtab_section->data; | 690 | p2 = (Elf32_Sym*)symtab_section->data; |
| 717 | 691 | ||
| 718 | for (j = 0; j < nb_syms; j++) { | 692 | for (j = 0; j < nb_syms; j++) { |
| 719 | if (p2->st_info == 0x12) { | 693 | if (p2->st_info == 0x12) { |
| 720 | // this is a func symbol | 694 | // this is a func symbol |
| 721 | 695 | ||
| 722 | name2 = | 696 | name2 = (char*)symtab_section->link->data + p2->st_name; |
| 723 | (char *) symtab_section->link->data + p2->st_name; | ||
| 724 | 697 | ||
| 725 | // find the function data index | 698 | // find the function data index |
| 726 | 699 | ||
| 727 | for (k = 0; k < nFuncs; k++) { | 700 | for (k = 0; k < nFuncs; k++) { |
| 728 | if (strcmp(name2, Func[k]) == 0) | 701 | if (strcmp(name2, Func[k]) == 0) |
| 729 | break; | 702 | break; |
| 730 | } | 703 | } |
| 731 | 704 | ||
| 732 | if (k >= nFuncs) { | 705 | if (k >= nFuncs) { |
| 733 | tcc_error("debug (sort) info can't find function: %s", name2); | 706 | tcc_error("debug (sort) info can't find function: %s", |
| 734 | } | 707 | name2); |
| 708 | } | ||
| 735 | 709 | ||
| 736 | if (strcmp(AssociatedFile[k], name) == 0) { | 710 | if (strcmp(AssociatedFile[k], name) == 0) { |
| 737 | // yes they match copy it over | 711 | // yes they match copy it over |
| 738 | 712 | ||
| 739 | NewTable[n++] = *p2; | 713 | NewTable[n++] = *p2; |
| 740 | } | 714 | } |
| 741 | } | 715 | } |
| 742 | p2++; | 716 | p2++; |
| 743 | } | 717 | } |
| 744 | } | 718 | } |
| 745 | p++; | 719 | p++; |
| 746 | } | 720 | } |
| 747 | 721 | ||
| 748 | // now all the filename and func symbols should have been copied over | 722 | // now all the filename and func symbols should have been copied over |
| 749 | // copy all the rest over (all except file and funcs) | 723 | // copy all the rest over (all except file and funcs) |
| 750 | 724 | ||
| 751 | p = (Elf32_Sym *) symtab_section->data; | 725 | p = (Elf32_Sym*)symtab_section->data; |
| 752 | for (i = 0; i < nb_syms; i++) { | 726 | for (i = 0; i < nb_syms; i++) { |
| 753 | if (p->st_info != 4 && p->st_info != 0x12) { | 727 | if (p->st_info != 4 && p->st_info != 0x12) { |
| 754 | NewTable[n++] = *p; | 728 | NewTable[n++] = *p; |
| 755 | } | 729 | } |
| 756 | p++; | 730 | p++; |
| 757 | } | 731 | } |
| 758 | 732 | ||
| 759 | if (n != nb_syms) | 733 | if (n != nb_syms) |
| 760 | tcc_error("Internal Compiler error, debug info"); | 734 | tcc_error("Internal Compiler error, debug info"); |
| 761 | 735 | ||
| 762 | // copy it all back | 736 | // copy it all back |
| 763 | 737 | ||
| 764 | p = (Elf32_Sym *) symtab_section->data; | 738 | p = (Elf32_Sym*)symtab_section->data; |
| 765 | for (i = 0; i < nb_syms; i++) { | 739 | for (i = 0; i < nb_syms; i++) { |
| 766 | *p++ = NewTable[i]; | 740 | *p++ = NewTable[i]; |
| 767 | } | 741 | } |
| 768 | 742 | ||
| 769 | tcc_free(NewTable); | 743 | tcc_free(NewTable); |
| 770 | } | 744 | } |
| 771 | 745 | ||
| 772 | 746 | int FindCoffSymbolIndex(const char* func_name) | |
| 773 | int FindCoffSymbolIndex(const char *func_name) | ||
| 774 | { | 747 | { |
| 775 | int i, n = 0; | 748 | int i, n = 0; |
| 776 | Elf32_Sym *p; | 749 | Elf32_Sym* p; |
| 777 | char *name; | 750 | char* name; |
| 778 | 751 | ||
| 779 | p = (Elf32_Sym *) symtab_section->data; | 752 | p = (Elf32_Sym*)symtab_section->data; |
| 780 | 753 | ||
| 781 | for (i = 0; i < nb_syms; i++) { | 754 | for (i = 0; i < nb_syms; i++) { |
| 782 | 755 | ||
| 783 | name = (char *) symtab_section->link->data + p->st_name; | 756 | name = (char*)symtab_section->link->data + p->st_name; |
| 784 | 757 | ||
| 785 | if (p->st_info == 4) { | 758 | if (p->st_info == 4) { |
| 786 | // put a filename symbol | 759 | // put a filename symbol |
| 787 | n++; | 760 | n++; |
| 788 | } else if (p->st_info == 0x12) { | 761 | } else if (p->st_info == 0x12) { |
| 789 | 762 | ||
| 790 | if (strcmp(func_name, name) == 0) | 763 | if (strcmp(func_name, name) == 0) |
| 791 | return n; | 764 | return n; |
| 792 | 765 | ||
| 793 | n += 6; | 766 | n += 6; |
| 794 | 767 | ||
| 795 | // put a Function Name | 768 | // put a Function Name |
| 796 | 769 | ||
| 797 | // now put aux info | 770 | // now put aux info |
| 798 | 771 | ||
| 799 | // put a .bf | 772 | // put a .bf |
| 800 | 773 | ||
| 801 | // now put aux info | 774 | // now put aux info |
| 802 | 775 | ||
| 803 | // put a .ef | 776 | // put a .ef |
| 804 | 777 | ||
| 805 | // now put aux info | 778 | // now put aux info |
| 806 | 779 | ||
| 807 | } else { | 780 | } else { |
| 808 | n += 2; | 781 | n += 2; |
| 809 | } | 782 | } |
| 810 | 783 | ||
| 811 | p++; | 784 | p++; |
| 812 | } | 785 | } |
| 813 | 786 | ||
| 814 | return n; // total number of symbols | 787 | return n; // total number of symbols |
| 815 | } | 788 | } |
| 816 | 789 | ||
| 817 | int OutputTheSection(Section * sect) | 790 | int OutputTheSection(Section* sect) |
| 818 | { | 791 | { |
| 819 | const char *s = sect->name; | 792 | const char* s = sect->name; |
| 820 | 793 | ||
| 821 | if (!strcmp(s, ".text")) | 794 | if (!strcmp(s, ".text")) |
| 822 | return 1; | 795 | return 1; |
| 823 | else if (!strcmp(s, ".data")) | 796 | else if (!strcmp(s, ".data")) |
| 824 | return 1; | 797 | return 1; |
| 825 | else | 798 | else |
| 826 | return 0; | 799 | return 0; |
| 827 | } | 800 | } |
| 828 | 801 | ||
| 829 | short int GetCoffFlags(const char *s) | 802 | short int GetCoffFlags(const char* s) |
| 830 | { | 803 | { |
| 831 | if (!strcmp(s, ".text")) | 804 | if (!strcmp(s, ".text")) |
| 832 | return STYP_TEXT | STYP_DATA | STYP_ALIGN | 0x400; | 805 | return STYP_TEXT | STYP_DATA | STYP_ALIGN | 0x400; |
| 833 | else if (!strcmp(s, ".data")) | 806 | else if (!strcmp(s, ".data")) |
| 834 | return STYP_DATA; | 807 | return STYP_DATA; |
| 835 | else if (!strcmp(s, ".bss")) | 808 | else if (!strcmp(s, ".bss")) |
| 836 | return STYP_BSS; | 809 | return STYP_BSS; |
| 837 | else if (!strcmp(s, ".stack")) | 810 | else if (!strcmp(s, ".stack")) |
| 838 | return STYP_BSS | STYP_ALIGN | 0x200; | 811 | return STYP_BSS | STYP_ALIGN | 0x200; |
| 839 | else if (!strcmp(s, ".cinit")) | 812 | else if (!strcmp(s, ".cinit")) |
| 840 | return STYP_COPY | STYP_DATA | STYP_ALIGN | 0x200; | 813 | return STYP_COPY | STYP_DATA | STYP_ALIGN | 0x200; |
| 841 | else | 814 | else |
| 842 | return 0; | 815 | return 0; |
| 843 | } | 816 | } |
| 844 | 817 | ||
| 845 | Section *FindSection(TCCState * s1, const char *sname) | 818 | Section* FindSection(TCCState* s1, const char* sname) |
| 846 | { | 819 | { |
| 847 | Section *s; | 820 | Section* s; |
| 848 | int i; | 821 | int i; |
| 849 | 822 | ||
| 850 | for (i = 1; i < s1->nb_sections; i++) { | 823 | for (i = 1; i < s1->nb_sections; i++) { |
| 851 | s = s1->sections[i]; | 824 | s = s1->sections[i]; |
| 852 | 825 | ||
| 853 | if (!strcmp(sname, s->name)) | 826 | if (!strcmp(sname, s->name)) |
| 854 | return s; | 827 | return s; |
| 855 | } | 828 | } |
| 856 | 829 | ||
| 857 | tcc_error("could not find section %s", sname); | 830 | tcc_error("could not find section %s", sname); |
| 858 | return 0; | 831 | return 0; |
| 859 | } | 832 | } |
| 860 | 833 | ||
| 861 | ST_FUNC int tcc_load_coff(TCCState * s1, int fd) | 834 | ST_FUNC int tcc_load_coff(TCCState* s1, int fd) |
| 862 | { | 835 | { |
| 863 | // tktk TokenSym *ts; | 836 | // tktk TokenSym *ts; |
| 864 | 837 | ||
| 865 | FILE *f; | 838 | FILE* f; |
| 866 | unsigned int str_size; | 839 | unsigned int str_size; |
| 867 | char *Coff_str_table, *name; | 840 | char* Coff_str_table, *name; |
| 868 | int i, k; | 841 | int i, k; |
| 869 | struct syment csym; | 842 | struct syment csym; |
| 870 | char name2[9]; | 843 | char name2[9]; |
| 871 | FILHDR file_hdr; /* FILE HEADER STRUCTURE */ | 844 | FILHDR file_hdr; /* FILE HEADER STRUCTURE */ |
| 872 | 845 | ||
| 873 | f = fdopen(fd, "rb"); | 846 | f = fdopen(fd, "rb"); |
| 874 | if (!f) { | 847 | if (!f) { |
| 875 | tcc_error("Unable to open .out file for input"); | 848 | tcc_error("Unable to open .out file for input"); |
| 876 | } | 849 | } |
| 877 | 850 | ||
| 878 | if (fread(&file_hdr, FILHSZ, 1, f) != 1) | 851 | if (fread(&file_hdr, FILHSZ, 1, f) != 1) |
| 879 | tcc_error("error reading .out file for input"); | 852 | tcc_error("error reading .out file for input"); |
| 880 | 853 | ||
| 881 | if (fread(&o_filehdr, sizeof(o_filehdr), 1, f) != 1) | 854 | if (fread(&o_filehdr, sizeof(o_filehdr), 1, f) != 1) |
| 882 | tcc_error("error reading .out file for input"); | 855 | tcc_error("error reading .out file for input"); |
| 883 | 856 | ||
| 884 | // first read the string table | 857 | // first read the string table |
| 885 | 858 | ||
| 886 | if (fseek(f, file_hdr.f_symptr + file_hdr.f_nsyms * SYMESZ, SEEK_SET)) | 859 | if (fseek(f, file_hdr.f_symptr + file_hdr.f_nsyms * SYMESZ, SEEK_SET)) |
| 887 | tcc_error("error reading .out file for input"); | 860 | tcc_error("error reading .out file for input"); |
| 888 | 861 | ||
| 889 | if (fread(&str_size, sizeof(int), 1, f) != 1) | 862 | if (fread(&str_size, sizeof(int), 1, f) != 1) |
| 890 | tcc_error("error reading .out file for input"); | 863 | tcc_error("error reading .out file for input"); |
| 891 | |||
| 892 | 864 | ||
| 893 | Coff_str_table = (char *) tcc_malloc(str_size); | 865 | Coff_str_table = (char*)tcc_malloc(str_size); |
| 894 | 866 | ||
| 895 | if (fread(Coff_str_table, str_size - 4, 1, f) != 1) | 867 | if (fread(Coff_str_table, str_size - 4, 1, f) != 1) |
| 896 | tcc_error("error reading .out file for input"); | 868 | tcc_error("error reading .out file for input"); |
| 897 | 869 | ||
| 898 | // read/process all the symbols | 870 | // read/process all the symbols |
| 899 | 871 | ||
| 900 | // seek back to symbols | 872 | // seek back to symbols |
| 901 | 873 | ||
| 902 | if (fseek(f, file_hdr.f_symptr, SEEK_SET)) | 874 | if (fseek(f, file_hdr.f_symptr, SEEK_SET)) |
| 903 | tcc_error("error reading .out file for input"); | 875 | tcc_error("error reading .out file for input"); |
| 904 | 876 | ||
| 905 | for (i = 0; i < file_hdr.f_nsyms; i++) { | 877 | for (i = 0; i < file_hdr.f_nsyms; i++) { |
| 906 | if (fread(&csym, SYMESZ, 1, f) != 1) | 878 | if (fread(&csym, SYMESZ, 1, f) != 1) |
| 907 | tcc_error("error reading .out file for input"); | 879 | tcc_error("error reading .out file for input"); |
| 908 | 880 | ||
| 909 | if (csym._n._n_n._n_zeroes == 0) { | 881 | if (csym._n._n_n._n_zeroes == 0) { |
| 910 | name = Coff_str_table + csym._n._n_n._n_offset - 4; | 882 | name = Coff_str_table + csym._n._n_n._n_offset - 4; |
| 911 | } else { | 883 | } else { |
| 912 | name = csym._n._n_name; | 884 | name = csym._n._n_name; |
| 913 | 885 | ||
| 914 | if (name[7] != 0) { | 886 | if (name[7] != 0) { |
| 915 | for (k = 0; k < 8; k++) | 887 | for (k = 0; k < 8; k++) |
| 916 | name2[k] = name[k]; | 888 | name2[k] = name[k]; |
| 917 | 889 | ||
| 918 | name2[8] = 0; | 890 | name2[8] = 0; |
| 919 | 891 | ||
| 920 | name = name2; | 892 | name = name2; |
| 921 | } | 893 | } |
| 922 | } | 894 | } |
| 923 | // if (strcmp("_DAC_Buffer",name)==0) // tktk | 895 | // if (strcmp("_DAC_Buffer",name)==0) // tktk |
| 924 | // name[0]=0; | 896 | // name[0]=0; |
| 925 | 897 | ||
| 926 | if (((csym.n_type & 0x30) == 0x20 && csym.n_sclass == 0x2) || ((csym.n_type & 0x30) == 0x30 && csym.n_sclass == 0x2) || (csym.n_type == 0x4 && csym.n_sclass == 0x2) || (csym.n_type == 0x8 && csym.n_sclass == 0x2) || // structures | 898 | if (((csym.n_type & 0x30) == 0x20 && csym.n_sclass == 0x2) || |
| 927 | (csym.n_type == 0x18 && csym.n_sclass == 0x2) || // pointer to structure | 899 | ((csym.n_type & 0x30) == 0x30 && csym.n_sclass == 0x2) || |
| 928 | (csym.n_type == 0x7 && csym.n_sclass == 0x2) || // doubles | 900 | (csym.n_type == 0x4 && csym.n_sclass == 0x2) || |
| 929 | (csym.n_type == 0x6 && csym.n_sclass == 0x2)) // floats | 901 | (csym.n_type == 0x8 && csym.n_sclass == 0x2) || // structures |
| 930 | { | 902 | (csym.n_type == 0x18 && |
| 931 | // strip off any leading underscore (except for other main routine) | 903 | csym.n_sclass == 0x2) || // pointer to structure |
| 932 | 904 | (csym.n_type == 0x7 && csym.n_sclass == 0x2) || // doubles | |
| 933 | if (name[0] == '_' && strcmp(name, "_main") != 0) | 905 | (csym.n_type == 0x6 && csym.n_sclass == 0x2)) // floats |
| 934 | name++; | 906 | { |
| 935 | 907 | // strip off any leading underscore (except for other main routine) | |
| 936 | tcc_add_symbol(s1, name, (void*)(uintptr_t)csym.n_value); | 908 | |
| 937 | } | 909 | if (name[0] == '_' && strcmp(name, "_main") != 0) |
| 938 | // skip any aux records | 910 | name++; |
| 939 | 911 | ||
| 940 | if (csym.n_numaux == 1) { | 912 | tcc_add_symbol(s1, name, (void*)(uintptr_t)csym.n_value); |
| 941 | if (fread(&csym, SYMESZ, 1, f) != 1) | 913 | } |
| 942 | tcc_error("error reading .out file for input"); | 914 | // skip any aux records |
| 943 | i++; | 915 | |
| 944 | } | 916 | if (csym.n_numaux == 1) { |
| 917 | if (fread(&csym, SYMESZ, 1, f) != 1) | ||
| 918 | tcc_error("error reading .out file for input"); | ||
| 919 | i++; | ||
| 920 | } | ||
| 945 | } | 921 | } |
| 946 | 922 | ||
| 947 | return 0; | 923 | return 0; |