Browse Source

first dumb repl on x86

mntmn 8 years ago
parent
commit
5f41241d1a
12 changed files with 188 additions and 57 deletions
  1. BIN
      build/interim.bin
  2. 2 4
      build_386.sh
  3. 1 10
      devices/bios.S
  4. 94 18
      devices/bios.c
  5. 12 6
      devices/bios.ld
  6. 0 3
      devices/debug_util.c
  7. 54 4
      devices/libc_glue.c
  8. 1 1
      qemu-386.sh
  9. 3 3
      sledge/alloc.c
  10. 1 1
      sledge/compiler_x86.c
  11. 10 0
      sledge/jit_x86.c
  12. 10 7
      sledge/sledge.c

BIN
build/interim.bin


+ 2 - 4
build_386.sh

@@ -1,6 +1,4 @@
-gcc -g -o build/interim.o --std=gnu99 -m32 -nostartfiles -nostdlib -ffreestanding devices/bios.S devices/bios.c -DCPU_X86 -lgcc
+gcc -T devices/bios.ld -o build/interim.bin --std=gnu99 -m32  -fno-asynchronous-unwind-tables -nostartfiles -nostdlib -ffreestanding -I/usr/include/newlib devices/bios.S devices/bios.c -DCPU_X86 -Isledge sledge/sledge.c sledge/reader.c sledge/writer.c sledge/alloc.c sledge/strmap.c sledge/stream.c -lgcc /home/mntmn/code/newlib/newlib/i686-elf/32/newlib/libc.a /home/mntmn/code/newlib/newlib/i686-elf/32/newlib/libm.a
 
-#gcc -g -o build/interim.o --std=gnu99 -m32 -nostartfiles -nostdlib -ffreestanding -Isledge sledge/sledge.c sledge/reader.c sledge/writer.c sledge/alloc.c sledge/strmap.c sledge/stream.c devices/bios.c devices/bios.S -DCPU_X86 ../dietlibc/bin-i386/dietlibc.a ../dietlibc/bin-i386/libm.a -lgcc
-
-ld -T devices/bios.ld -m elf_i386 --build-id=none -o build/interim.bin -nostdlib build/interim.o
+#gcc -T devices/bios.ld -m32 -o build/interim.bin -ffreestanding -nostdlib build/interim.o
 

+ 1 - 10
devices/bios.S

@@ -16,15 +16,6 @@
 .long FLAGS
 .long CHECKSUM
 
-# Currently the stack pointer register (esp) points at anything and using it may
-# cause massive harm. Instead, we'll provide our own stack. We will allocate
-# room for a small temporary stack by creating a symbol at the bottom of it,
-# then allocating 16384 bytes for it, and finally creating a symbol at the top.
-.section .bootstrap_stack, "aw", @nobits
-stack_bottom:
-.skip 16384 # 16 KiB
-stack_top:
-
 # The linker script specifies _start as the entry point to the kernel and the
 # bootloader will jump to this position once the kernel has been loaded. It
 # doesn't make sense to return from this function as the bootloader is gone.
@@ -54,7 +45,7 @@ _start:
 
 	# To set up a stack, we simply set the esp register to point to the top of
 	# our stack (as it grows downwards).
-	movl $stack_top, %esp
+	movl $0x200000, %esp
 
   movw $0xf41, %si
   movw %si, (0xb8000)

+ 94 - 18
devices/bios.c

@@ -3,6 +3,8 @@
 #include <stdint.h>
 #include <stdio.h>
 #include <string.h>
+
+static void* heap_end;
  
 /* Check if the compiler thinks if we are targeting the wrong operating system. */
 //#if defined(__linux__)
@@ -57,9 +59,9 @@ static const size_t VGA_HEIGHT = 25;
 size_t terminal_row;
 size_t terminal_column;
 uint8_t terminal_color;
+uint16_t* terminal_buffer;
  
 void terminal_initialize() {
-  uint16_t* terminal_buffer;
 	terminal_row = 0;
 	terminal_column = 0;
 	terminal_color = make_color(COLOR_LIGHT_GREY, COLOR_BLACK);
@@ -77,12 +79,19 @@ void terminal_setcolor(uint8_t color) {
 }
  
 void terminal_putentryat(char c, uint8_t color, size_t x, size_t y) {
-  uint16_t* terminal_buffer;
 	const size_t index = y * VGA_WIDTH + x;
 	terminal_buffer[index] = make_vgaentry(c, color);
 }
  
 void terminal_putchar(char c) {
+  if (c==10) {
+    terminal_column=0;
+    terminal_row++;
+    if (terminal_row == VGA_HEIGHT) {
+      terminal_initialize();
+    }
+    return;
+  }
 	terminal_putentryat(c, terminal_color, terminal_column, terminal_row);
 	if (++terminal_column == VGA_WIDTH) {
 		terminal_column = 0;
@@ -91,36 +100,103 @@ void terminal_putchar(char c) {
 		}
 	}
 }
- 
+
 void terminal_writestring(const char* data) {
 	size_t datalen = strlen(data);
 	for (size_t i = 0; i < datalen; i++)
 		terminal_putchar(data[i]);
 }
 
-void kernel_main() {
-  *((uint16_t*)0xB8000) = 0xf42;
-  uint16_t* terminal_buffer;
+int bios_getc(void)
+{
+  uint16_t key_to_rune[] = {
+    0,
+    0,
+    '1','2','3','4','5','6','7','8','9','0','/','"',9,
+    '\t','q','w','e','r','t','z','u','i','o','p','-','+',10,
+    0,'a','s','d','f','g','h','j','k','l','(',')',0,0,'*',
+    'y','x','c','v','b','n','m',',','.','-',0,
+    0,0,' ',
+    0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0
+  };
+
+	int key;
+
+  __asm("WaitLoop:   in     $0x64, %al");
+  __asm(            "and    $1, %al");
+  __asm(            "jz     WaitLoop");
+  __asm(            "in     $0x60, %al");
   
-  terminal_buffer = (uint16_t*)0xB8000;
-  for (register int i=0; i<256; i++) {
-    terminal_buffer[i]='X'|(COLOR_WHITE << 8);
+  __asm("mov %%al,%0" : "=m" (key));
+  if (key>0 && key<0x70) {
+    return(key_to_rune[key]);
+  } else {
+    return 0;
   }
+}
+
+void uart_puts(char* str) {
+  terminal_writestring(str);
+}
 
-  *((uint16_t*)0xB8000) = 0xf43;
+void uart_putc(char c) {
+  terminal_putchar(c);
+}
+
+char uart_getc() {
+  return bios_getc();
+}
+
+#define GETLINE_MAX 256
+static char getline_buf[GETLINE_MAX];
+
+ssize_t getline(char **lineptr, size_t *n, FILE *stream) {
+  printf("\r\n");
+  int i = 0;
+  int k = 0;
+  while (k!=10 && i<GETLINE_MAX) {
+    k = uart_getc();
+    if (k>0) {
+      uart_putc(k);
+      getline_buf[i] = k;
+      i++;
+    }
+  }
+  *n = i;
+  *lineptr = getline_buf;
   
-  while(1) {};
+  return i;
+}
+
+#include "debug_util.c"
+#include "libc_glue.c"
+
+int main(int argc, char *argv[]);
+
+void kernel_main() {
+  terminal_buffer = (uint16_t*)0xB8000;
+  for (int i=0; i<80*23; i++) {
+    terminal_buffer[i]='*'|(COLOR_WHITE << 8);
+  }
   
 	/* Initialize terminal interface */
 	terminal_initialize();
- 
-	/* Since there is no support for newlines in terminal_putchar
-         * yet, '\n' will produce some VGA specific character instead.
-         * This is normal.
-         */
-	terminal_writestring("Hello, kernel World!\n");
+
+  heap_end = (void*)0x200000;
+
+  main(0,NULL);
 }
 
-extern _IO_ssize_t getline(char **__restrict __lineptr, size_t *__restrict __n, FILE *__restrict __stream) {
+/*extern _IO_ssize_t getline(char **__restrict __lineptr, size_t *__restrict __n, FILE *__restrict __stream) {
   return 0;
 }
+*/

+ 12 - 6
devices/bios.ld

@@ -18,27 +18,33 @@ SECTIONS
 		*(.multiboot)
 		*(.text)
 	}
-
+  
 	/* Read-only data. */
-	.rodata BLOCK(4K) : ALIGN(4K)
+	.rodata : ALIGN(4K)
 	{
 		*(.rodata)
 	}
-
+  
 	/* Read-write data (initialized) */
-	.data BLOCK(4K) : ALIGN(4K)
+	.data : ALIGN(4K)
 	{
 		*(.data)
 	}
 
 	/* Read-write data (uninitialized) and stack */
-	.bss BLOCK(4K) : ALIGN(4K)
+	.bss : ALIGN(4K)
 	{
 		*(COMMON)
 		*(.bss)
-		*(.bootstrap_stack)
 	}
 
+  .note.gnu.build-id : {
+    *(.note.gnu.build-id)
+  }
+   
+
 	/* The compiler may produce other sections, by default it will put them in
 	   a segment with the same name. Simply add stuff here as needed. */
 }
+
+

+ 0 - 3
devices/debug_util.c

@@ -1,9 +1,6 @@
 #include <stdint.h>
 #include <stdio.h>
 
-void uart_putc(unsigned char byte);
-void uart_puts(const char* str);
-
 void memdump(void* start,uint32_t len,int raw) {
   for (uint32_t i=0; i<len;) {
     if (!raw) printf("%08x | ",start+i);

+ 54 - 4
devices/libc_glue.c

@@ -1,6 +1,5 @@
 void _exit(int status) {
   uart_puts("-- clib exit called. hanging.\r\n");
-  memcpy(FB, (uint32_t*)0x200000, 1920*1080*4);
   
 	while (1) {
     uart_putc(uart_getc());
@@ -9,11 +8,11 @@ void _exit(int status) {
 
 void* _sbrk(int incr)
 {
-  uart_puts("-- sbrk: ");
+  /*uart_puts("-- sbrk: ");
   printhex((uint32_t)heap_end);
   uart_puts(" ");
   printhex_signed(incr);
-  uart_puts("\r\n");
+  uart_puts("\r\n");*/
   
   uint8_t* prev_heap_end;
 
@@ -23,6 +22,11 @@ void* _sbrk(int incr)
   return (void*)prev_heap_end;
 }
 
+void* sbrk(int incr)
+{
+  return _sbrk(incr);
+}
+
 void _kill() {
   uart_puts("-- clib kill called. not implemented.\r\n");
 }
@@ -42,11 +46,26 @@ int _close() {
   return 1;
 }
 
+int open() {
+  uart_puts("-- clib open called. stubbed.\r\n");
+  return 1;
+}
+
+int close() {
+  uart_puts("-- clib close called. stubbed.\r\n");
+  return 1;
+}
+
 int _fstat() {
   //uart_puts("-- clib fstat called. stubbed.\n");
   return 0;
 }
 
+int fstat() {
+  //uart_puts("-- clib fstat called. stubbed.\n");
+  return 0;
+}
+
 int _fseek() {
   //uart_puts("-- clib fseek called. stubbed.\n");
   return 0;
@@ -57,13 +76,36 @@ int _lseek() {
   return 0;
 }
 
+int lseek() {
+  //uart_puts("-- clib lseek called. stubbed.\n");
+  return 0;
+}
+
+int __sseek64() {
+  //uart_puts("-- clib lseek called. stubbed.\n");
+  return 0;
+}
+
 int _read() {
   //uart_puts("-- clib read called. stubbed.\n");
   return 0;
 }
 
+int read() {
+  //uart_puts("-- clib read called. stubbed.\n");
+  return 0;
+}
+
 size_t _write(int fildes, const void *buf, size_t nbytes) {
-  //uart_puts("-- clib write called:\n");
+  uart_puts("-- clib _write called:\n");
+  for (int i=0; i<nbytes; i++) {
+    uart_putc(((char*)buf)[i]);
+  }
+  return nbytes;
+}
+
+size_t write(int fildes, const void *buf, size_t nbytes) {
+  uart_puts("-- clib write called:\n");
   for (int i=0; i<nbytes; i++) {
     uart_putc(((char*)buf)[i]);
   }
@@ -74,3 +116,11 @@ int _fini() {
   uart_puts("-- clib _fini called. stubbed.\n");
   return 0;
 }
+
+// this is actually used
+size_t __swrite64(int fildes, int cookie, const void *buf, size_t nbytes) {
+  for (int i=0; i<nbytes; i++) {
+    uart_putc(((char*)buf)[i]);
+  }
+  return nbytes;
+}

+ 1 - 1
qemu-386.sh

@@ -1 +1 @@
-qemu-system-i386 -kernel build/interim.bin
+qemu-system-i386 -m 512M -kernel build/interim.bin

+ 3 - 3
sledge/alloc.c

@@ -315,7 +315,7 @@ Cell* alloc_sym(char* str) {
   
   sym->tag = TAG_SYM;
   if (str) {
-    int sz = strnlen(str,128)+1;
+    int sz = strlen(str)+1;
     sym->size = sz;
     //printf("alloc_sym: %s (%d)\r\n",str,sz);
     //memdump(sym,sizeof(Cell),0);
@@ -415,8 +415,8 @@ Cell* alloc_concat(Cell* str1, Cell* str2) {
   //printf("### str2: #%s#\n",str2->addr);
   
   Cell* cell = cell_alloc();
-  int size1 = strnlen(str1->addr,str1->size);
-  int size2 = strnlen(str2->addr,str2->size);
+  int size1 = strlen(str1->addr); // ,str2->size
+  int size2 = strlen(str2->addr);
   int newsize = size1+size2+1;
   cell->addr = bytes_alloc(newsize+1);
   cell->size = newsize;

+ 1 - 1
sledge/compiler_x86.c

@@ -46,7 +46,7 @@ int compile_for_platform(Cell* expr, Cell** res) {
 
     if (bytes_read>codesz) {
       printf("<error: max assembly size of %d exhausted. aborting>\n",codesz);
-      munmap(jit_binary,codesz);
+      //munmap(jit_binary,codesz);
       return 0;
     }
       

+ 10 - 0
sledge/jit_x86.c

@@ -60,6 +60,10 @@ void jit_movne(int dreg, int sreg) {
   fprintf(jit_out, "cmovne %s, %s\n", regnames[sreg], regnames[dreg]);
 }
 
+void jit_moveq(int dreg, int sreg) {
+  fprintf(jit_out, "cmoveq %s, %s\n", regnames[sreg], regnames[dreg]);
+}
+
 void jit_lea(int reg, void* addr) {
   fprintf(jit_out, "movq $%p, %s\n", addr, regnames[reg]);
 }
@@ -162,6 +166,9 @@ void jit_call(void* func, char* note) {
   fprintf(jit_out, "callq *%%rax # %s\n", note);
 }
 
+void jit_callr(int dreg) {
+}
+
 int32_t inline_mod(int a, int b) {
   return a%b;
 }
@@ -211,3 +218,6 @@ void jit_pop(int r1, int r2) {
     fprintf(jit_out, "pop %s\n",regnames[i]);
   }
 }
+
+void debug_handler() {
+}

+ 10 - 7
sledge/sledge.c

@@ -4,7 +4,7 @@
 #include "minilisp.h"
 #include <stdint.h>
 #include <stdlib.h>
-#include <sys/mman.h> // mprotect
+//#include <sys/mman.h> // mprotect
 
 Cell* platform_eval(Cell* expr); // FIXME
 
@@ -24,6 +24,8 @@ Cell* platform_eval(Cell* expr); // FIXME
 
 ssize_t getline(char **lineptr, size_t *n, FILE *stream);
 
+void terminal_writestring(const char* data);
+
 int main(int argc, char *argv[])
 {
   Cell* expr = NULL;
@@ -34,7 +36,7 @@ int main(int argc, char *argv[])
   size_t len = 0;
 
   init_compiler();
-  filesystems_init();
+  //filesystems_init();
 
 #ifdef DEV_SDL2
   void dev_sdl2_init();
@@ -66,7 +68,7 @@ int main(int argc, char *argv[])
   mount_consolekeys();
 #endif
 
-  FILE* in_file = stdin;  
+  FILE* in_file = stdin;
 
   if (argc==2) {
     in_file = fopen(argv[1],"r");
@@ -75,7 +77,7 @@ int main(int argc, char *argv[])
   while (1) {
     expr = NULL;
     
-    printf(KWHT "sledge> ");
+    printf("sledge> ");
     len = 0;
     int r = getline(&in_line, &len, in_file);
 
@@ -108,8 +110,9 @@ int main(int argc, char *argv[])
     
     if (expr) {      
       Cell* res;
-      int success = compile_for_platform(expr, &res); 
-
+      int success = 1; //compile_for_platform(expr, &res); 
+      res = expr;
+      
       if (success) {
         // OK
         if (res<cell_heap_start) {
@@ -117,7 +120,7 @@ int main(int argc, char *argv[])
         } else {
           char out_buf[1024*10];
           lisp_write(res, out_buf, 1024*10);
-          printf(KCYN "\n%s\n\n" KWHT,out_buf);
+          printf("\n%s\n\n",out_buf);
         }
       } else {
         printf("<compilation failed>\n");