1 |
dpavlin |
16 |
/* |
2 |
|
|
* Copyright (C) 2005 Anders Gavare. All rights reserved. |
3 |
|
|
* |
4 |
|
|
* Redistribution and use in source and binary forms, with or without |
5 |
|
|
* modification, are permitted provided that the following conditions are met: |
6 |
|
|
* |
7 |
|
|
* 1. Redistributions of source code must retain the above copyright |
8 |
|
|
* notice, this list of conditions and the following disclaimer. |
9 |
|
|
* 2. Redistributions in binary form must reproduce the above copyright |
10 |
|
|
* notice, this list of conditions and the following disclaimer in the |
11 |
|
|
* documentation and/or other materials provided with the distribution. |
12 |
|
|
* 3. The name of the author may not be used to endorse or promote products |
13 |
|
|
* derived from this software without specific prior written permission. |
14 |
|
|
* |
15 |
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
16 |
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 |
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 |
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
19 |
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
20 |
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
21 |
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
22 |
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
23 |
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
24 |
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
25 |
|
|
* SUCH DAMAGE. |
26 |
|
|
* |
27 |
|
|
* |
28 |
|
|
* $Id: generate_arm_r.c,v 1.1 2005/10/09 21:32:07 debug Exp $ |
29 |
|
|
* |
30 |
|
|
* Generate functions for computing "reg" operands. |
31 |
|
|
*/ |
32 |
|
|
|
33 |
|
|
#include <stdio.h> |
34 |
|
|
#include <stdlib.h> |
35 |
|
|
|
36 |
|
|
|
37 |
|
|
#if 0 |
38 |
|
|
/* |
39 |
|
|
* update_c is set if the C flag should be updated with the last shifted/ |
40 |
|
|
* rotated bit. |
41 |
|
|
*/ |
42 |
|
|
uint32_t R(struct cpu *cpu, struct arm_instr_call *ic, |
43 |
|
|
uint32_t iword, int update_c) |
44 |
|
|
{ |
45 |
|
|
int rm = iword & 15, lastbit, t, c; |
46 |
|
|
uint32_t tmp = cpu->cd.arm.r[rm]; |
47 |
|
|
|
48 |
|
|
case 2: /* lsr #c (c = 1..32) */ |
49 |
|
|
if (c == 0) |
50 |
|
|
c = 32; |
51 |
|
|
if (update_c) { |
52 |
|
|
lastbit = ((uint64_t)tmp >> (c-1)) & 1; |
53 |
|
|
} |
54 |
|
|
tmp = (uint64_t)tmp >> c; |
55 |
|
|
break; |
56 |
|
|
case 3: /* lsr Rc */ |
57 |
|
|
c = cpu->cd.arm.r[c >> 1] & 255; |
58 |
|
|
if (c >= 32) |
59 |
|
|
c = 33; |
60 |
|
|
if (update_c) { |
61 |
|
|
if (c == 0) |
62 |
|
|
update_c = 0; |
63 |
|
|
else |
64 |
|
|
lastbit = ((uint64_t)tmp >> (c-1)) & 1; |
65 |
|
|
} |
66 |
|
|
tmp = (uint64_t)tmp >> c; |
67 |
|
|
break; |
68 |
|
|
case 4: /* asr #c (c = 1..32) */ |
69 |
|
|
if (c == 0) |
70 |
|
|
c = 32; |
71 |
|
|
if (update_c) { |
72 |
|
|
lastbit = ((int64_t)(int32_t)tmp >> (c-1)) & 1; |
73 |
|
|
} |
74 |
|
|
tmp = (int64_t)(int32_t)tmp >> c; |
75 |
|
|
break; |
76 |
|
|
case 5: /* asr Rc */ |
77 |
|
|
c = cpu->cd.arm.r[c >> 1] & 255; |
78 |
|
|
if (c >= 32) |
79 |
|
|
c = 33; |
80 |
|
|
if (update_c) { |
81 |
|
|
if (c == 0) |
82 |
|
|
update_c = 0; |
83 |
|
|
else |
84 |
|
|
lastbit = ((int64_t)(int32_t)tmp >> (c-1)) & 1; |
85 |
|
|
} |
86 |
|
|
tmp = (int64_t)(int32_t)tmp >> c; |
87 |
|
|
break; |
88 |
|
|
case 6: /* ror 1..31 */ |
89 |
|
|
if (c == 0) { |
90 |
|
|
fatal("TODO: rrx\n"); |
91 |
|
|
exit(1); |
92 |
|
|
} |
93 |
|
|
if (update_c) |
94 |
|
|
lastbit = ((int64_t)(int32_t)tmp >> (c-1)) & 1; |
95 |
|
|
tmp = (uint64_t)(((uint64_t)tmp << 32) | tmp) >> c; |
96 |
|
|
break; |
97 |
|
|
case 7: /* ror Rc */ |
98 |
|
|
c = cpu->cd.arm.r[c >> 1] & 255; |
99 |
|
|
if (update_c) { |
100 |
|
|
if (c == 0) |
101 |
|
|
update_c = 0; |
102 |
|
|
else { |
103 |
|
|
c &= 31; |
104 |
|
|
if (c == 0) |
105 |
|
|
lastbit = tmp & 0x80000000; |
106 |
|
|
else |
107 |
|
|
lastbit = ((int64_t)(int32_t)tmp |
108 |
|
|
>> (c-1)) & 1; |
109 |
|
|
tmp = (uint64_t)(((uint64_t)tmp << 32) |
110 |
|
|
| tmp) >> c; |
111 |
|
|
} |
112 |
|
|
} |
113 |
|
|
break; |
114 |
|
|
} |
115 |
|
|
if (update_c) { |
116 |
|
|
cpu->cd.arm.cpsr &= ~ARM_FLAG_C; |
117 |
|
|
if (lastbit) |
118 |
|
|
cpu->cd.arm.cpsr |= ARM_FLAG_C; |
119 |
|
|
} |
120 |
|
|
return tmp; |
121 |
|
|
} |
122 |
|
|
#endif |
123 |
|
|
|
124 |
|
|
|
125 |
|
|
void sync_pc(void) |
126 |
|
|
{ |
127 |
|
|
printf("\tuint32_t tmp, low_pc = ((size_t)ic - (size_t)\n" |
128 |
|
|
"\t cpu->cd.arm.cur_ic_page)/sizeof(struct arm_instr_call);\n"); |
129 |
|
|
printf("\ttmp = cpu->cd.arm.r[15] & ~((ARM_IC_ENTRIES_PER_PAGE-1) <<\n" |
130 |
|
|
"\t ARM_INSTR_ALIGNMENT_SHIFT);\n"); |
131 |
|
|
printf("\ttmp += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT) + 8;\n"); |
132 |
|
|
} |
133 |
|
|
|
134 |
|
|
|
135 |
|
|
void f(int s, int func, int only_name) |
136 |
|
|
{ |
137 |
|
|
int rm = func & 15; |
138 |
|
|
int c = (func >> 7) & 31; |
139 |
|
|
int t = (func >> 4) & 7; |
140 |
|
|
char name[200]; |
141 |
|
|
int pc = rm == 15, rc = c >> 1; |
142 |
|
|
|
143 |
|
|
snprintf(name, sizeof(name), "arm_r%s_r%i_t%i_c%i", s? "s" : "", |
144 |
|
|
rm, t, c); |
145 |
|
|
if (only_name) { |
146 |
|
|
printf("%s", name); |
147 |
|
|
return; |
148 |
|
|
} |
149 |
|
|
|
150 |
|
|
printf("uint32_t %s(struct cpu *cpu, struct arm_instr_call *ic)" |
151 |
|
|
" {\n", name); |
152 |
|
|
if (pc) |
153 |
|
|
sync_pc(); |
154 |
|
|
|
155 |
|
|
switch (t) { |
156 |
|
|
|
157 |
|
|
case 0: /* lsl c (Logical Shift Left by constant) */ |
158 |
|
|
if (s) { |
159 |
|
|
printf("{ uint32_t x = "); |
160 |
|
|
if (pc) |
161 |
|
|
printf("tmp"); |
162 |
|
|
else |
163 |
|
|
printf("cpu->cd.arm.r[%i]", rm); |
164 |
|
|
printf(";\n"); |
165 |
|
|
if (c != 0) { |
166 |
|
|
printf("cpu->cd.arm.cpsr &= ~ARM_FLAG_C;\n"); |
167 |
|
|
printf("if (x & 0x%x)\n" |
168 |
|
|
"\tcpu->cd.arm.cpsr |= ARM_FLAG_C;\n", |
169 |
|
|
(int)(0x80000000 >> (c-1))); |
170 |
|
|
printf("x <<= %i;\n", c); |
171 |
|
|
} |
172 |
|
|
printf(" return x; }\n"); |
173 |
|
|
} else { |
174 |
|
|
if (pc) |
175 |
|
|
printf("\treturn tmp"); |
176 |
|
|
else |
177 |
|
|
printf("\treturn cpu->cd.arm.r[%i]", rm); |
178 |
|
|
if (c != 0) |
179 |
|
|
printf(" << %i", c); |
180 |
|
|
printf(";\n"); |
181 |
|
|
} |
182 |
|
|
break; |
183 |
|
|
|
184 |
|
|
case 1: /* lsl Rc (Logical Shift Left by register) */ |
185 |
|
|
if (s) { |
186 |
|
|
printf("{ uint32_t x = "); |
187 |
|
|
if (pc) |
188 |
|
|
printf("tmp"); |
189 |
|
|
else |
190 |
|
|
printf("cpu->cd.arm.r[%i]", rm); |
191 |
|
|
printf(";\n"); |
192 |
|
|
printf(" uint32_t y = cpu->cd.arm.r[%i] & 255;\n", rc); |
193 |
|
|
printf(" if (y != 0) {\n"); |
194 |
|
|
printf(" cpu->cd.arm.cpsr &= ~ARM_FLAG_C;\n"); |
195 |
|
|
printf(" if (y >= 32) return 0;\n"); |
196 |
|
|
printf(" x <<= (y - 1);\n"); |
197 |
|
|
printf(" if (x & 0x80000000)\n" |
198 |
|
|
"\tcpu->cd.arm.cpsr |= ARM_FLAG_C;\n"); |
199 |
|
|
printf(" x <<= 1;\n"); |
200 |
|
|
printf(" }\n"); |
201 |
|
|
printf(" return x; }\n"); |
202 |
|
|
} else { |
203 |
|
|
printf("{ uint32_t y = cpu->cd.arm.r[%i] & 255;\n", rc); |
204 |
|
|
printf(" uint32_t x ="); |
205 |
|
|
if (pc) |
206 |
|
|
printf("tmp"); |
207 |
|
|
else |
208 |
|
|
printf("cpu->cd.arm.r[%i]", rm); |
209 |
|
|
printf(";\n"); |
210 |
|
|
printf("if (y > 31) return 0; else x <<= y;\n"); |
211 |
|
|
printf("return x; }\n"); |
212 |
|
|
} |
213 |
|
|
break; |
214 |
|
|
|
215 |
|
|
case 2: /* lsr c (Logical Shift Right by constant) */ |
216 |
|
|
/* 1..32 */ |
217 |
|
|
if (s) { |
218 |
|
|
printf("{ uint32_t x = "); |
219 |
|
|
if (pc) |
220 |
|
|
printf("tmp"); |
221 |
|
|
else |
222 |
|
|
printf("cpu->cd.arm.r[%i]", rm); |
223 |
|
|
printf(";\n"); |
224 |
|
|
if (c == 0) |
225 |
|
|
c = 32; |
226 |
|
|
printf("cpu->cd.arm.cpsr &= ~ARM_FLAG_C;\n"); |
227 |
|
|
printf("if (x & 0x%x)\n" |
228 |
|
|
"\tcpu->cd.arm.cpsr |= ARM_FLAG_C;\n", |
229 |
|
|
(int)(1 << (c-1))); |
230 |
|
|
if (c == 32) |
231 |
|
|
printf("x = 0;\n"); |
232 |
|
|
else |
233 |
|
|
printf("x >>= %i;\n", c); |
234 |
|
|
printf(" return x; }\n"); |
235 |
|
|
} else { |
236 |
|
|
if (c == 0) |
237 |
|
|
printf("\treturn 0;\n"); |
238 |
|
|
else { |
239 |
|
|
if (pc) |
240 |
|
|
printf("\treturn tmp"); |
241 |
|
|
else |
242 |
|
|
printf("\treturn cpu->cd.arm.r[%i]",rm); |
243 |
|
|
printf(" >> %i;\n", c); |
244 |
|
|
} |
245 |
|
|
} |
246 |
|
|
break; |
247 |
|
|
|
248 |
|
|
case 3: /* lsr Rc (Logical Shift Right by register) */ |
249 |
|
|
if (s) { |
250 |
|
|
printf("{ uint32_t x = "); |
251 |
|
|
if (pc) |
252 |
|
|
printf("tmp"); |
253 |
|
|
else |
254 |
|
|
printf("cpu->cd.arm.r[%i]", rm); |
255 |
|
|
printf(",y=cpu->cd.arm.r[%i]&255;\n", rc); |
256 |
|
|
printf("if(y==0) return x;\n"); |
257 |
|
|
printf("cpu->cd.arm.cpsr &= ~ARM_FLAG_C;\n"); |
258 |
|
|
printf("if(y>31) y=32;\n"); |
259 |
|
|
printf("y--; x >>= y;\n"); |
260 |
|
|
printf("if (x & 1) " |
261 |
|
|
"cpu->cd.arm.cpsr |= ARM_FLAG_C;\n"); |
262 |
|
|
printf(" return x >> 1; }\n"); |
263 |
|
|
} else { |
264 |
|
|
printf("{ uint32_t y=cpu->cd.arm.r[%i]&255;\n", rc); |
265 |
|
|
printf("uint32_t x="); |
266 |
|
|
if (pc) |
267 |
|
|
printf("tmp"); |
268 |
|
|
else |
269 |
|
|
printf("cpu->cd.arm.r[%i]",rm); |
270 |
|
|
printf("; "); |
271 |
|
|
printf("if (y>=32) return 0;\n"); |
272 |
|
|
printf("return x >> y; } "); |
273 |
|
|
} |
274 |
|
|
break; |
275 |
|
|
|
276 |
|
|
case 4: /* asr c (Arithmetic Shift Right by constant) */ |
277 |
|
|
/* 1..32 */ |
278 |
|
|
if (s) { |
279 |
|
|
printf("{ int32_t x = "); |
280 |
|
|
if (pc) |
281 |
|
|
printf("tmp"); |
282 |
|
|
else |
283 |
|
|
printf("cpu->cd.arm.r[%i]", rm); |
284 |
|
|
printf(";\n"); |
285 |
|
|
if (c == 0) |
286 |
|
|
c = 32; |
287 |
|
|
printf("cpu->cd.arm.cpsr &= ~ARM_FLAG_C;\n"); |
288 |
|
|
printf("if (x & 0x%x)\n" |
289 |
|
|
"\tcpu->cd.arm.cpsr |= ARM_FLAG_C;\n", |
290 |
|
|
(int)(1 << (c-1))); |
291 |
|
|
if (c == 32) |
292 |
|
|
printf("x = (x<0)? 0xffffffff : 0;\n"); |
293 |
|
|
else |
294 |
|
|
printf("x >>= %i;\n", c); |
295 |
|
|
printf(" return x; }\n"); |
296 |
|
|
} else { |
297 |
|
|
if (c == 0) { |
298 |
|
|
printf("\treturn "); |
299 |
|
|
if (pc) |
300 |
|
|
printf("tmp"); |
301 |
|
|
else |
302 |
|
|
printf("cpu->cd.arm.r[%i]",rm); |
303 |
|
|
printf(" & 0x80000000? 0xffffffff : 0;\n"); |
304 |
|
|
} else { |
305 |
|
|
printf("return (int32_t)"); |
306 |
|
|
if (pc) |
307 |
|
|
printf("tmp"); |
308 |
|
|
else |
309 |
|
|
printf("cpu->cd.arm.r[%i]",rm); |
310 |
|
|
printf(" >> %i;\n", c); |
311 |
|
|
} |
312 |
|
|
} |
313 |
|
|
break; |
314 |
|
|
|
315 |
|
|
case 5: /* asr Rc (Arithmetic Shift Right by register) */ |
316 |
|
|
if (s) { |
317 |
|
|
printf("{ int32_t x = "); |
318 |
|
|
if (pc) |
319 |
|
|
printf("tmp"); |
320 |
|
|
else |
321 |
|
|
printf("cpu->cd.arm.r[%i]", rm); |
322 |
|
|
printf(",y=cpu->cd.arm.r[%i]&255;\n", rc); |
323 |
|
|
printf("if(y==0) return x;\n"); |
324 |
|
|
printf("cpu->cd.arm.cpsr &= ~ARM_FLAG_C;\n"); |
325 |
|
|
printf("if(y>31) y=31;\n"); |
326 |
|
|
printf("y--; x >>= y;\n"); |
327 |
|
|
printf("if (x & 1) " |
328 |
|
|
"cpu->cd.arm.cpsr |= ARM_FLAG_C;\n"); |
329 |
|
|
printf(" return (int32_t)x >> 1; }\n"); |
330 |
|
|
} else { |
331 |
|
|
printf("{ int32_t y=cpu->cd.arm.r[%i]&255;\n", rc); |
332 |
|
|
printf("int32_t x="); |
333 |
|
|
if (pc) |
334 |
|
|
printf("tmp"); |
335 |
|
|
else |
336 |
|
|
printf("cpu->cd.arm.r[%i]",rm); |
337 |
|
|
printf("; "); |
338 |
|
|
printf("if (y>=31) return (x<0)?0xffffffff:0;\n"); |
339 |
|
|
printf("return (int32_t)x >> y; } "); |
340 |
|
|
} |
341 |
|
|
break; |
342 |
|
|
|
343 |
|
|
case 6: /* ror c OR rrx (Arithmetic Shift Right by constant) */ |
344 |
|
|
/* 0=rrx, 1..31=ror */ |
345 |
|
|
if (c == 0) { |
346 |
|
|
printf("\tprintf(\"%s\\n\");\n", name); |
347 |
|
|
printf("\texit(1); /* TODO */\n\treturn 0;\n"); |
348 |
|
|
} else if (s) { |
349 |
|
|
printf("{ uint64_t x = "); |
350 |
|
|
if (pc) |
351 |
|
|
printf("tmp"); |
352 |
|
|
else |
353 |
|
|
printf("cpu->cd.arm.r[%i]", rm); |
354 |
|
|
printf("; x |= (x << 32);\n"); |
355 |
|
|
printf("cpu->cd.arm.cpsr &= ~ARM_FLAG_C;\n"); |
356 |
|
|
printf("if (x & 0x%x)\n" |
357 |
|
|
"\tcpu->cd.arm.cpsr |= ARM_FLAG_C;\n", |
358 |
|
|
(int)(1 << (c-1))); |
359 |
|
|
printf(" return x >> %i; }\n", c); |
360 |
|
|
} else { |
361 |
dpavlin |
18 |
printf("{ uint64_t x="); |
362 |
dpavlin |
16 |
if (pc) |
363 |
|
|
printf("tmp"); |
364 |
|
|
else |
365 |
|
|
printf("cpu->cd.arm.r[%i]",rm); |
366 |
|
|
printf("; x |= (x << 32); "); |
367 |
dpavlin |
18 |
printf("return x >> %i; }\n", c); |
368 |
dpavlin |
16 |
} |
369 |
|
|
break; |
370 |
|
|
|
371 |
|
|
case 7: /* ror Rc (Rotate Right by register) */ |
372 |
|
|
if (s) { |
373 |
|
|
printf("{ uint64_t x = "); |
374 |
|
|
if (pc) |
375 |
|
|
printf("tmp"); |
376 |
|
|
else |
377 |
|
|
printf("cpu->cd.arm.r[%i]", rm); |
378 |
|
|
printf("; int y=cpu->cd.arm.r[%i]&255;\n", rc); |
379 |
|
|
printf("if(y==0) return x;\n"); |
380 |
|
|
printf("y --; y &= 31; x >>= y;\n"); |
381 |
|
|
printf("cpu->cd.arm.cpsr &= ~ARM_FLAG_C;\n"); |
382 |
|
|
printf("if (x & 1) " |
383 |
|
|
"cpu->cd.arm.cpsr |= ARM_FLAG_C;\n"); |
384 |
|
|
printf(" return x >> 1; }\n"); |
385 |
|
|
} else { |
386 |
|
|
printf("{ int y=cpu->cd.arm.r[%i]&31;\n", rc); |
387 |
|
|
printf("uint64_t x="); |
388 |
|
|
if (pc) |
389 |
|
|
printf("tmp"); |
390 |
|
|
else |
391 |
|
|
printf("cpu->cd.arm.r[%i]",rm); |
392 |
|
|
printf("; x |= (x << 32); "); |
393 |
|
|
printf("return (x >> y); } "); |
394 |
|
|
} |
395 |
|
|
break; |
396 |
|
|
|
397 |
|
|
default: |
398 |
|
|
printf("\tprintf(\"%s\\n\");\n", name); |
399 |
|
|
printf("\texit(1); /* TODO */\n\treturn 0;\n"); |
400 |
|
|
} |
401 |
|
|
|
402 |
|
|
printf("}\n"); |
403 |
|
|
} |
404 |
|
|
|
405 |
|
|
|
406 |
|
|
int main(int argc, char *argv[]) |
407 |
|
|
{ |
408 |
|
|
int s, func, f_start, f_end; |
409 |
|
|
|
410 |
|
|
if (argc < 3) { |
411 |
|
|
fprintf(stderr, "usage: %s start end\n", argv[0]); |
412 |
|
|
exit(1); |
413 |
|
|
} |
414 |
|
|
|
415 |
|
|
f_start = strtol(argv[1], NULL, 0); |
416 |
|
|
f_end = strtol(argv[2], NULL, 0); |
417 |
|
|
|
418 |
|
|
printf("/*\n * DO NOT EDIT! AUTOMATICALLY GENERATED!\n */\n\n"); |
419 |
|
|
printf("#include <stdio.h>\n"); |
420 |
|
|
printf("#include <stdlib.h>\n"); |
421 |
|
|
printf("#include \"cpu.h\"\n"); |
422 |
|
|
printf("#include \"misc.h\"\n"); |
423 |
|
|
printf("\n\n"); |
424 |
|
|
|
425 |
|
|
if (f_start != 0 || f_end != 0) { |
426 |
|
|
for (s=0; s<=1; s++) |
427 |
|
|
for (func=f_start; func<=f_end; func++) |
428 |
|
|
f(s, func, 0); |
429 |
|
|
} else { |
430 |
|
|
for (s=0; s<=1; s++) |
431 |
|
|
for (func=0; func<=0xfff; func++) { |
432 |
|
|
printf("extern uint32_t "); |
433 |
|
|
f(s, func, 1); |
434 |
|
|
printf("(struct cpu *, struct arm_" |
435 |
|
|
"instr_call *);\n"); |
436 |
|
|
} |
437 |
|
|
|
438 |
|
|
printf("\nuint32_t (*arm_r[8192])(struct cpu *," |
439 |
|
|
" struct arm_instr_call *) = {\n"); |
440 |
|
|
for (s=0; s<=1; s++) |
441 |
|
|
for (func=0; func<=0xfff; func++) { |
442 |
|
|
printf("\t"); |
443 |
|
|
f(s, func, 1); |
444 |
|
|
if (s!=1 || func!=0xfff) |
445 |
|
|
printf(","); |
446 |
|
|
printf("\n"); |
447 |
|
|
} |
448 |
|
|
printf("};\n\n"); |
449 |
|
|
} |
450 |
|
|
|
451 |
|
|
return 0; |
452 |
|
|
} |
453 |
|
|
|