mescc: Produce M1 output instead of hex2.
[mes.git] / mlibc / libc-gcc.c
1 /* -*-comment-start: "//";comment-end:""-*-
2  * Mes --- Maxwell Equations of Software
3  * Copyright © 2016,2017 Jan Nieuwenhuizen <janneke@gnu.org>
4  *
5  * This file is part of Mes.
6  *
7  * Mes is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or (at
10  * your option) any later version.
11  *
12  * Mes is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with Mes.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 char **g_environment = 0;
22 int g_stdin = 0;
23
24 #include <stdio.h>
25 #include <mlibc.h>
26
27 #if __GNUC__
28 #include <stdlib.h>
29 #endif
30
31 #if __GNUC__ && !POSIX
32
33 void
34 exit (int code)
35 {
36   asm (
37        "mov    %0,%%ebx\n\t"
38        "mov    $1,%%eax\n\t"
39        "int    $0x80"
40        : // no outputs "=" (r)
41        : "" (code)
42        );
43   // not reached
44   exit (0);
45 }
46
47 int
48 read (int fd, void* buf, size_t n)
49 {
50   int r;
51   //syscall (SYS_write, fd, s, n));
52   asm (
53        "mov    %1,%%ebx\n\t"
54        "mov    %2,%%ecx\n\t"
55        "mov    %3,%%edx\n\t"
56
57        "movl $0x3,%%eax\n\t"
58        "int  $0x80\n\t"
59
60        "mov    %%eax,%0\n\t"
61        : "=r" (r)
62        : "" (fd), "" (buf), "" (n)
63        : "eax", "ebx", "ecx", "edx"
64        );
65   return r;
66 }
67
68 int
69 write (int fd, char const* s, int n)
70 {
71   int r;
72   //syscall (SYS_write, fd, s, n));
73   asm (
74        "mov    %1,%%ebx\n\t"
75        "mov    %2,%%ecx\n\t"
76        "mov    %3,%%edx\n\t"
77
78        "mov    $0x4, %%eax\n\t"
79        "int    $0x80\n\t"
80        "mov    %%eax,%0\n\t"
81        : "=r" (r)
82        : "" (fd), "" (s), "" (n)
83        : "eax", "ebx", "ecx", "edx"
84        );
85   return r;
86 }
87
88 int
89 open (char const *s, int flags, ...)
90 {
91   int mode;
92   asm (
93        "mov    %%ebp,%%eax\n\t"
94        "add    $0x10,%%eax\n\t"
95        "mov    (%%eax),%%eax\n\t"
96        "mov    %%eax,%0\n\t"
97        : "=mode" (mode)
98        : //no inputs ""
99        );
100   int r;
101   //syscall (SYS_open, mode));
102   asm (
103        "mov    %1,%%ebx\n\t"
104        "mov    %2,%%ecx\n\t"
105        "mov    %3,%%edx\n\t"
106        "mov    $0x5,%%eax\n\t"
107        "int    $0x80\n\t"
108        "mov    %%eax,%0\n\t"
109        : "=r" (r)
110        : "" (s), "" (flags), "" (mode)
111        : "eax", "ebx", "ecx", "edx"
112        );
113   return r;
114 }
115
116 int
117 access (char const *s, int mode)
118 {
119   int r;
120   //syscall (SYS_access, mode));
121   asm (
122        "mov    %1,%%ebx\n\t"
123        "mov    %2,%%ecx\n\t"
124        "mov    $0x21,%%eax\n\t"
125        "int    $0x80\n\t"
126        "mov    %%eax,%0\n\t"
127        : "=r" (r)
128        : "" (s), "" (mode)
129        : "eax", "ebx", "ecx"
130        );
131   return r;
132 }
133
134 void *
135 brk (void *p)
136 {
137   void *r;
138   asm (
139        "mov    %1,%%ebx\n\t"
140
141        "mov    $0x2d,%%eax\n\t"
142        "int    $0x80\n\t"
143
144        "mov    %%eax,%0\n\t"
145        : "=r" (r)
146        : "" (p)
147        : "eax", "ebx"
148        );
149   return r;
150 }
151
152 int
153 fsync (int fd)
154 {
155   int r;
156   //syscall (SYS_fsync, fd));
157   asm (
158        "mov    %1,%%ebx\n\t"
159
160        "mov    $0x76, %%eax\n\t"
161        "int    $0x80\n\t"
162        "mov    %%eax,%0\n\t"
163        : "=r" (r)
164        : "" (fd)
165        : "eax", "ebx"
166        );
167   return r;
168 }
169
170 int
171 fputc (int c, int fd)
172 {
173   write (fd, (char*)&c, 1);
174   return 0;
175 }
176
177 int
178 putchar (int c)
179 {
180   write (STDOUT, (char*)&c, 1);
181   return 0;
182 }
183
184 void *g_malloc_base = 0;
185
186 void *
187 malloc (size_t size)
188 {
189   void *p = brk (0);
190   if (!g_malloc_base) g_malloc_base = p;
191   brk (p+size);
192   return p;
193 }
194
195 void *
196 realloc (void *p, size_t size)
197 {
198   (void)p;
199   brk (g_malloc_base + size);
200   return g_malloc_base;
201 }
202
203 void
204 free (void *p)
205 {
206   int *n = (int*)p-1;
207   //munmap ((void*)p, *n);
208 }
209
210 size_t
211 strlen (char const* s)
212 {
213   int i = 0;
214   while (s[i]) i++;
215   return i;
216 }
217
218 int
219 strcmp (char const* a, char const* b)
220 {
221   while (*a && *b && *a == *b) {a++;b++;}
222   return *a - *b;
223 }
224
225 char *
226 strcpy (char *dest, char const *src)
227 {
228   char *p = dest;
229   while (*src) *p++ = *src++;
230   *p = 0;
231   return dest;
232 }
233
234 int
235 eputs (char const* s)
236 {
237   int i = strlen (s);
238   write (STDERR, s, i);
239   return 0;
240 }
241
242 int
243 fputs (char const* s, int fd)
244 {
245   int i = strlen (s);
246   write (fd, s, i);
247   return 0;
248 }
249
250 int
251 puts (char const* s)
252 {
253   int i = strlen (s);
254   write (STDOUT, s, i);
255   return 0;
256 }
257
258 void
259 assert_fail (char* s)
260 {
261   eputs ("assert fail: ");
262   eputs (s);
263   eputs ("\n");
264   *((int*)0) = 0;
265 }
266
267 #define assert(x) ((x) ? (void)0 : assert_fail (#x))
268
269 int ungetc_char = -1;
270 char ungetc_buf[2];
271
272 int
273 getchar ()
274 {
275   char c;
276   int i;
277   if (ungetc_char == -1)
278     {
279       int r = read (g_stdin, &c, 1);
280       if (r < 1) return -1;
281       i = c;
282     }
283   else
284     i = ungetc_buf[ungetc_char--];
285
286   if (i < 0) i += 256;
287
288   return i;
289 }
290
291 int
292 ungetc (int c, int fd)
293 {
294   assert (ungetc_char < 2);
295   ungetc_buf[++ungetc_char] = c;
296   return c;
297 }
298
299 char const* itoa (int);
300
301 int
302 strncmp (char const* a, char const* b, size_t length)
303 {
304   while (*a && *b && *a == *b && --length) {a++;b++;}
305   return *a - *b;
306 }
307
308 char *
309 getenv (char const* s)
310 {
311   char **p = g_environment;
312   int length = strlen (s);
313   while (*p)
314     {
315       if (!strncmp (s, *p, length) && *(*p + length) == '=') return (*p + length + 1);
316       p++;
317     }
318   return 0;
319 }
320
321 int
322 isdigit (int c)
323 {
324   return (c>='0') && (c<='9');
325 }
326
327 int
328 atoi (char const *s)
329 {
330   int i = 0;
331   int sign = 1;
332   if (*s && *s == '-')
333     {
334       sign = -1;
335       s++;
336     }
337   while (isdigit (*s))
338     {
339       i *= 10;
340       i += (*s - '0');
341       s++;
342     }
343   return i * sign;
344 }
345
346 int
347 printf (char const* format, ...)
348 {
349   int va_arg = 0;
350   int va;
351   char const *p = format;
352   while (*p)
353     if (*p != '%')
354       putchar (*p++);
355     else
356       {
357         p++;
358         char c = *p;
359         switch (c)
360           {
361           case '%': {putchar (*p); break;}
362           case 'c':
363             {
364             asm (
365                  "mov    -0xc(%%ebp),%%eax\n\t"
366                  "shl     $0x2,%%eax\n\t"
367                  "add     %%ebp,%%eax\n\t"
368                  "add     $0xc,%%eax\n\t"
369                  "mov     (%%eax),%%eax\n\t"
370                  //"mov     %%eax,%0\n\t"
371                  : "=va" (va)
372                  : //no inputs ""
373                  );
374             putchar ((char)va);
375             va_arg++;
376             break;
377             }
378           case 'd': {
379             asm (
380                  "mov    -0xc(%%ebp),%%eax\n\t"
381                  "shl     $0x2,%%eax\n\t"
382                  "add     %%ebp,%%eax\n\t"
383                  "add     $0xc,%%eax\n\t"
384                  "mov     (%%eax),%%eax\n\t"
385                  //"mov     %%eax,%0\n\t"
386                  : "=va" (va)
387                  : //no inputs ""
388                  );
389             puts (itoa ((int)va));
390             va_arg++;
391             break;
392           }
393           case 's': {
394             asm (
395                  "mov    -0xc(%%ebp),%%eax\n\t"
396                  "shl     $0x2,%%eax\n\t"
397                  "add     %%ebp,%%eax\n\t"
398                  "add     $0xc,%%eax\n\t"
399                  "mov     (%%eax),%%eax\n\t"
400                  //"mov     %%eax,%0\n\t"
401                  : "=va" (va)
402                  : //no inputs ""
403                  );
404             puts ((char*)va);
405             va_arg++;
406             break;
407           }
408           default: putchar (*p);
409           }
410         p++;
411       }
412   return 0;
413 }
414 #endif
415
416 char itoa_buf[10];
417
418 char const*
419 itoa (int x)
420 {
421   //static char itoa_buf[10];
422   //char *p = buf+9;
423   char *p = itoa_buf;
424   p += 9;
425   *p-- = 0;
426
427   //int sign = x < 0;
428   int sign;
429   sign = x < 0;
430   if (sign)
431     x = -x;
432
433   do
434     {
435       *p-- = '0' + (x % 10);
436       x = x / 10;
437     } while (x);
438
439   if (sign)
440     *p-- = '-';
441
442   return p+1;
443 }
444
445 #if POSIX
446 #define _GNU_SOURCE
447 #include <assert.h>
448 #include <fcntl.h>
449 #include <string.h>
450 #include <unistd.h>
451 #endif // POSIX
452
453 int
454 fdputs (char const* s, int fd)
455 {
456   int i = strlen (s);
457   write (fd, s, i);
458   return 0;
459 }
460
461 #if POSIX
462
463 int
464 fdputc (int c, int fd)
465 {
466   write (fd, (char*)&c, 1);
467   return 0;
468 }
469
470 int
471 putchar (int c)
472 {
473   write (STDOUT, (char*)&c, 1);
474   return 0;
475 }
476
477 int ungetc_char = -1;
478 char ungetc_buf[2];
479
480 int
481 getchar ()
482 {
483   char c;
484   int i;
485   if (ungetc_char == -1)
486     {
487       int r = read (g_stdin, &c, 1);
488       if (r < 1) return -1;
489       i = c;
490     }
491   else
492     i = ungetc_buf[ungetc_char--];
493
494   if (i < 0) i += 256;
495
496   return i;
497 }
498
499 int
500 fdungetc (int c, int fd)
501 {
502   assert (ungetc_char < 2);
503   ungetc_buf[++ungetc_char] = c;
504   return c;
505 }
506
507 #endif // POSIX
508
509 #if __GNUC__ && !POSIX
510 void
511 _start ()
512 {
513   //  char **;
514   asm (
515        "mov     %%ebp,%%eax\n\t"
516        "addl    $4,%%eax\n\t"
517        "movzbl  (%%eax),%%eax\n\t"
518        "addl    $3,%%eax\n\t"
519        "shl     $2,%%eax\n\t"
520        "add     %%ebp,%%eax\n\t"
521        "movl    %%eax,%0\n\t"
522        : "=g_environment" (g_environment)
523        : //no inputs ""
524        );
525   int r;
526   asm (
527        "mov     %%ebp,%%eax\n\t"
528        "addl    $8,%%eax\n\t"
529        "push    %%eax\n\t"
530
531        "mov     %%ebp,%%eax\n\t"
532        "addl    $4,%%eax\n\t"
533        "movzbl  (%%eax),%%eax\n\t"
534        "push     %%eax\n\t"
535
536        "call    main\n\t"
537        "movl    %%eax,%0\n\t"
538        : "=r" (r)
539        : //no inputs ""
540        );
541   exit (r);
542 }
543 #endif // __GNUC__ && !POSIX