From 3e1a197ed16f0f3e3a9660dc11514ca236b7b719 Mon Sep 17 00:00:00 2001 From: Jan Nieuwenhuizen Date: Tue, 14 Aug 2018 20:32:56 +0200 Subject: [PATCH] mescc: Initial x86_64 support. make all-go && MES=guile ./pre-inst-env scripts/mescc -m64 -c scaffold/main.c --- .gitignore | 2 +- build-aux/build-guile.sh | 2 + build-aux/build-x86_64-mes.sh | 56 ++++--- build-aux/cc-x86_64-mes.sh | 67 ++++++++ build-aux/config.sh | 3 +- lib/linux/x86_64-mes-gcc/crt1.c | 4 +- lib/linux/x86_64-mes/crt1 | Bin 0 -> 352 bytes lib/linux/x86_64-mes/crt1.c | 58 +++++++ lib/x86-mes/x86.M1 | 8 +- lib/x86_64-mes/elf64-footer-single-main.hex2 | 2 +- lib/x86_64-mes/elf64-header.hex2 | 11 +- lib/x86_64-mes/x86_64.M1 | 50 ++++++ mes/module/mescc/i386/as.mes | 1 + mes/module/mescc/i386/info.mes | 23 +++ mes/module/mescc/mescc.mes | 4 +- mes/module/mescc/x86_64/as.mes | 23 +++ mes/module/mescc/x86_64/info.mes | 23 +++ module/mescc/as.scm | 8 +- module/mescc/compile.scm | 151 +++++++++++++++---- module/mescc/i386/as.scm | 60 ++++++-- module/mescc/i386/info.scm | 3 +- module/mescc/info.scm | 18 ++- module/mescc/mescc.scm | 63 ++++++-- module/mescc/preprocess.scm | 1 - module/mescc/x86_64/as.scm | 91 +++++++++++ module/mescc/x86_64/info.scm | 68 +++++++++ scripts/mescc.in | 5 + 27 files changed, 702 insertions(+), 103 deletions(-) create mode 100755 build-aux/cc-x86_64-mes.sh create mode 100644 lib/linux/x86_64-mes/crt1 create mode 100644 lib/linux/x86_64-mes/crt1.c create mode 100644 lib/x86_64-mes/x86_64.M1 create mode 100644 mes/module/mescc/i386/info.mes create mode 100644 mes/module/mescc/x86_64/as.mes create mode 100644 mes/module/mescc/x86_64/info.mes create mode 100644 module/mescc/x86_64/as.scm create mode 100644 module/mescc/x86_64/info.scm diff --git a/.gitignore b/.gitignore index c3fc54c5..da8824a8 100644 --- a/.gitignore +++ b/.gitignore @@ -37,10 +37,10 @@ *.x86-out *.x86_64-mes-gcc-o *.x86_64-mes-gcc-out +*.x86_64-mes-o *.x86_64-mes-out *.x86_64-out - /src/*.h /src/*.i /src/mes diff --git a/build-aux/build-guile.sh b/build-aux/build-guile.sh index 1a93fab6..4e28d253 100755 --- a/build-aux/build-guile.sh +++ b/build-aux/build-guile.sh @@ -39,6 +39,8 @@ ${srcdest}module/mescc/bytevectors.scm ${srcdest}module/mescc/compile.scm ${srcdest}module/mescc/i386/as.scm ${srcdest}module/mescc/i386/info.scm +${srcdest}module/mescc/x86_64/as.scm +${srcdest}module/mescc/x86_64/info.scm ${srcdest}module/mescc/info.scm ${srcdest}module/mescc/mescc.scm ${srcdest}module/mescc/preprocess.scm diff --git a/build-aux/build-x86_64-mes.sh b/build-aux/build-x86_64-mes.sh index c1576710..c7eff73e 100755 --- a/build-aux/build-x86_64-mes.sh +++ b/build-aux/build-x86_64-mes.sh @@ -105,27 +105,28 @@ trace "TEST lib/x86_64-mes/exit-42.x86_64-out" echo lib/x86_64-mes/exit-42 # -o lib/x86_64-mes/libc+tcc.o # fi -# PREPROCESS=1 -# if [ ! -d "$MES_SEED" ] \ -# && [ "$ARCH" = "i386" \ -# -o "$ARCH" = "i586" \ -# -o "$ARCH" = "i686" ]; then -# MES_ARENA=100000000 -# fi -# MES_ARENA=100000000 -# ARCHDIR=1 NOLINK=1 bash ${srcdest}build-aux/cc-mes.sh lib/linux/crt0 -# ARCHDIR=1 NOLINK=1 bash ${srcdest}build-aux/cc-mes.sh lib/libc-mini +PREPROCESS=1 +if [ ! -d "$MES_SEED" ] \ + && [ "$ARCH" = "i386" \ + -o "$ARCH" = "i586" \ + -o "$ARCH" = "i686" ]; then + MES_ARENA=100000000 +fi -# PREPROCESS= bash ${srcdest}build-aux/cc-mes.sh lib/x86_64-mes/exit-42 +ARCHDIR=1 NOLINK=1 bash ${srcdest}build-aux/cc-x86_64-mes.sh lib/linux/x86_64-mes/crt1 -# trace "TEST exit-42.x86_64-mes-out" -# { set +e; lib/x86_64-mes/exit-42.x86_64-mes-out; r=$?; set -e; } -# [ $r != 42 ] && echo " => $r" && exit 1 +MES_LIBS='-l none' PREPROCESS= bash ${srcdest}build-aux/cc-x86_64-mes.sh lib/x86_64-mes/exit-42 -# ARCHDIR=1 NOLINK=1 bash ${srcdest}build-aux/cc-mes.sh lib/linux/crt1 -# ARCHDIR=1 NOLINK=1 bash ${srcdest}build-aux/cc-mes.sh lib/linux/crti -# ARCHDIR=1 NOLINK=1 bash ${srcdest}build-aux/cc-mes.sh lib/linux/crtn +trace "TEST lib/x86_64-mes/exit-42.x86_64-mes-out" echo lib/x86_64-mes/exit-42.x86_64-mes-out +{ set +e; lib/x86_64-mes/exit-42.x86_64-mes-out; r=$?; set -e; } +[ $r != 42 ] && echo " => $r" && exit 1 + +# ARCHDIR=1 NOLINK=1 bash ${srcdest}build-aux/cc-x86_64-mes.sh lib/libc-mini + +# ARCHDIR=1 NOLINK=1 bash ${srcdest}build-aux/cc-mes.sh lib/linux/x86_64-mes/crt0 +# ARCHDIR=1 NOLINK=1 bash ${srcdest}build-aux/cc-mes.sh lib/linux/x86_64-mes/crti +# ARCHDIR=1 NOLINK=1 bash ${srcdest}build-aux/cc-mes.sh lib/linux/x86_64-mes/crtn # ARCHDIR=1 NOLINK=1 bash ${srcdest}build-aux/cc-mes.sh lib/libc # ARCHDIR=1 NOLINK=1 bash ${srcdest}build-aux/cc-mes.sh lib/libgetopt @@ -147,13 +148,18 @@ trace "TEST lib/x86_64-mes/exit-42.x86_64-out" echo lib/x86_64-mes/exit-42 # echo MES_ARENA=$MES_ARENA # bash ${srcdest}build-aux/cc-mes.sh scaffold/main -# bash ${srcdest}build-aux/cc-mes.sh scaffold/main -# bash ${srcdest}build-aux/cc-mes.sh scaffold/hello -# bash ${srcdest}build-aux/cc-mes.sh scaffold/argv -# bash ${srcdest}build-aux/cc-mes.sh scaffold/malloc -# ##sh ${srcdest}build-aux/cc-mes.sh scaffold/micro-mes -# ##sh ${srcdest}build-aux/cc-mes.sh scaffold/tiny-mes -# # bash ${srcdest}build-aux/cc-mes.sh scaffold/mini-mes -# bash ${srcdest}build-aux/cc-mes.sh src/mes +MES_LIBS='-l none' bash ${srcdest}build-aux/cc-x86_64-mes.sh scaffold/main + +trace "TEST scaffold/main.x86_64-mes-out" echo scaffold/main.x86_64-mes-out +{ set +e; scaffold/main.x86_64-mes-out; r=$?; set -e; } +[ $r != 42 ] && echo " => $r" && exit 1 + +# MES_LIBS='-l mini' bash ${srcdest}build-aux/cc-x86_64-mes.sh scaffold/hello +# MES_LIBS='-l mini' bash ${srcdest}build-aux/cc-x86_64-mes.sh scaffold/argv +# bash ${srcdest}build-aux/cc-x86_64-mes.sh scaffold/malloc +# ##sh ${srcdest}build-aux/cc-x86_64-mes.sh scaffold/micro-mes +# ##sh ${srcdest}build-aux/cc-x86_64-mes.sh scaffold/tiny-mes +# # bash ${srcdest}build-aux/cc-x86_64-mes.sh scaffold/mini-mes +# bash ${srcdest}build-aux/cc-x86_64-mes.sh src/mes # cp src/mes.mes-out src/mes true diff --git a/build-aux/cc-x86_64-mes.sh b/build-aux/cc-x86_64-mes.sh new file mode 100755 index 00000000..e551b07d --- /dev/null +++ b/build-aux/cc-x86_64-mes.sh @@ -0,0 +1,67 @@ +#! /bin/sh + +# GNU Mes --- Maxwell Equations of Software +# Copyright © 2018 Jan (janneke) Nieuwenhuizen +# +# This file is part of GNU Mes. +# +# GNU Mes is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or (at +# your option) any later version. +# +# GNU Mes is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Mes. If not, see . + +set -e + +. ${srcdest}build-aux/config.sh +. ${srcdest}build-aux/trace.sh + +MESCC=${MESCC-$(command -v mescc)} +[ -z "$MESCC" ] && MESCC=scripts/mescc +MES=${MES-$(command -v mes)} +[ -z "$MES" ] && MES=src/mes + +if [ "$V" = 2 ]; then + MES64_CFLAGS="$MES64_CFLAGS -v" +fi + +c=$1 + +set -e + +if [ -z "$ARCHDIR" ]; then + o="$c" + d=${c%%/*} + p="x86_64-mes-" +else + b=${c##*/} + d=${c%%/*}/x86_64-mes + o="$d/$b" +fi +mkdir -p $d + +if [ -n "$PREPROCESS" ]; then + trace "CPP.mes64 $c.c" ./pre-inst-env bash $MESCC $MES_CPPFLAGS $MES64_CFLAGS -E -o "$o.E" "${srcdest}$c".c + trace "CC.mes64 $c.E" ./pre-inst-env bash $MESCC $MES64_CFLAGS -S "$o".E + trace "AS.mes64 $c.S" ./pre-inst-env bash $MESCC $MES64_CFLAGS -c -o "$o".${p}o "$o".S + if [ -z "$NOLINK" ]; then + trace "LD.mes64 $c.o" ./pre-inst-env bash $MESCC $MES64_CFLAGS -o "$o".${p}out "$o".${p}o $MES_LIBS + fi +elif [ -n "$COMPILE" ]; then + trace "CC.mes64 $c.c" trace "MESCC $c.c" ./pre-inst-env bash $MESCC $MES_CPPFLAGS $MES64_CFLAGS -S -o "$o.S" "${srcdest}$c".c + trace "AS.mes64 $c.S" ./pre-inst-env bash $MESCC $MES64_CFLAGS -c -o "$o".${p}o "$o".S + if [ -z "$NOLINK" ]; then + trace "LD.mes64 $c.o" ./pre-inst-env bash $MESCC $MES64_CFLAGS -o "$o".${p}out "$o".${p}o $MES_LIBS + fi +elif [ -z "$NOLINK" ]; then + trace "CC.mes64 $c.c" ./pre-inst-env bash $MESCC $MES_CPPFLAGS $MES64_CFLAGS -o "$o".${p}out "${srcdest}$c".c $MES_LIBS +else + trace "CC.mes64 $c.c" ./pre-inst-env bash $MESCC $MES_CPPFLAGS $MES64_CFLAGS -c -o "$o".${p}o "${srcdest}$c".c +fi diff --git a/build-aux/config.sh b/build-aux/config.sh index 4fa84441..f1a84886 100644 --- a/build-aux/config.sh +++ b/build-aux/config.sh @@ -153,7 +153,8 @@ MES_CPPFLAGS=${MES_CPPFLAGS-" MES_CFLAGS=${MES_CFLAGS-" "} -MES_CFLAGS=${MES_CFLAGS-" +MES64_CFLAGS=${MES64_CFLAGS-" +-m64 "} M1FLAGS=${M1FLAGS-" diff --git a/lib/linux/x86_64-mes-gcc/crt1.c b/lib/linux/x86_64-mes-gcc/crt1.c index 4693e0f6..e1c6619c 100644 --- a/lib/linux/x86_64-mes-gcc/crt1.c +++ b/lib/linux/x86_64-mes-gcc/crt1.c @@ -28,9 +28,9 @@ void _start () { asm ( - "movq %%rbp,%%rax\n\t" + "mov %%rbp,%%rax\n\t" "add $8,%%rax\n\t" - "movq (%%rax),%%rax\n\t" + "mov (%%rax),%%rax\n\t" "add $3,%%rax\n\t" "shl $3,%%rax\n\t" "add %%rbp,%%rax\n\t" diff --git a/lib/linux/x86_64-mes/crt1 b/lib/linux/x86_64-mes/crt1 new file mode 100644 index 0000000000000000000000000000000000000000..80ac20f31c36517d9d239d2c8341e6cdc2fb7955 GIT binary patch literal 352 zcmb<-^>JfjWMqH=CI&kOFpn8RIlv?kN*Ej%EP#>@4D1XnU`6aOH4qx65=?Jlh6uuF zWJz-L`ML(9*oMw$&?`x;C}Ge`Ni0cZ&`ZwG%}vb%a*H#HONvSolYp$sTnG)}qZmd6 V2j+g5QV<`6* + * + * This file is part of GNU Mes. + * + * GNU Mes is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * GNU Mes is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Mes. If not, see . + */ + +char **environ = 0; +int main (int argc, char *argv[]); + +int +_start () +{ + asm ("mov____%rbp,%rax"); + asm ("add____$i8,%rax !8"); + + asm ("mov____(%rax),%rax"); + asm ("add____$i8,%rax !0x03"); + + asm ("shl____$i8,%rax !0x03"); + asm ("add____%rbp,%rax"); + + // 40017a: 48 a3 88 77 66 55 44 movabs %rax,0x1122334455667788 + // 48 89 05 bd 0e 20 00 mov %rax,0x200ebd(%rip) # 601000 <_GLOBAL_OFFSET_TABLE_> + // FIXME: 64-bit addresses...DUNNO! + // asm ("mov____%rax,0x32 &environ"); + + asm ("mov____%rbp,%rax"); + asm ("add____$i8,%rax !16"); + asm ("mov____%rax,%rsi"); + + asm ("mov____%rbp,%rax"); + asm ("add____$i8,%rax !8"); + asm ("mov____(%rax),%rax"); + asm ("mov____%rax,%rdi"); + + main (); + // FIXME + //asm ("call32 &main !00 !00 !00 !00"); + + asm ("mov____%rax,%rdi"); + asm ("mov____$i32,%rax %0x3c"); + asm ("syscall"); + asm ("hlt"); +} diff --git a/lib/x86-mes/x86.M1 b/lib/x86-mes/x86.M1 index 43f06acc..978f3309 100644 --- a/lib/x86-mes/x86.M1 +++ b/lib/x86-mes/x86.M1 @@ -186,13 +186,13 @@ DEFINE setne__%al 0f95c0 DEFINE shl____$i8,%eax c1e0 DEFINE shl____%cl,%eax d3e0 DEFINE shr____%cl,%eax d3e8 +DEFINE sub____$8,%esp 83ec +DEFINE sub____$i32,%esp 81ec DEFINE sub____%al,%dl 28d0 DEFINE sub____%dl,%al 28c2 DEFINE sub____%eax,%edx 29c2 DEFINE sub____%edx,%eax 29d0 DEFINE sub____%edx,%eax 29d0 -DEFINE sub____%esp,$i32 81ec -DEFINE sub____%esp,$i8 83ec DEFINE test___%al,%al 84c0 DEFINE test___%eax,%eax 85c0 DEFINE xchg___%eax,(%esp) 870424 @@ -204,6 +204,10 @@ DEFINE xor____%ecx,%ecx 31c9 DEFINE xor____%edx,%eax 31d0 DEFINE xor____%edx,%edx 31d2 +# deprecated, remove after 0.18 +DEFINE sub____%esp,$i32 81ec +DEFINE sub____%esp,$i8 83ec + DEFINE SYS_exit 01000000 DEFINE SYS_fork 02000000 DEFINE SYS_read 03000000 diff --git a/lib/x86_64-mes/elf64-footer-single-main.hex2 b/lib/x86_64-mes/elf64-footer-single-main.hex2 index 6caed915..16275111 100644 --- a/lib/x86_64-mes/elf64-footer-single-main.hex2 +++ b/lib/x86_64-mes/elf64-footer-single-main.hex2 @@ -34,7 +34,7 @@ 00 00 00 -# @240 +# @370 :ELF_sym 00 00 00 00 # st-name 00 # st-info = stt-func= 2 diff --git a/lib/x86_64-mes/elf64-header.hex2 b/lib/x86_64-mes/elf64-header.hex2 index 582b8743..174f4f8c 100644 --- a/lib/x86_64-mes/elf64-header.hex2 +++ b/lib/x86_64-mes/elf64-header.hex2 @@ -36,10 +36,12 @@ 00 00 00 00 00 00 00 # e_ident[EI_PAD] +# 0x10 02 00 # e_type Indicating Executable 3e 00 # e_machine Indicating AMD64 01 00 00 00 # e_version Indicating original elf +# 0x18 &ELF_text 00 00 00 00 # e_entry Address of the entry point %ELF_program_headers>ELF_base # e_phoff Address of program header table 00 00 00 00 @@ -126,7 +128,7 @@ 00 00 00 00 00 00 00 00 # sh_length 00 00 00 00 # sh_link 00 00 00 00 # sh_info -01 00 00 00 00 00 00 00 # sh_1? +00 00 00 00 00 00 00 00 # sh_1? 00 00 00 00 00 00 00 00 # sh_entsize ## FIXME: M0 for calculations? @@ -180,9 +182,6 @@ :ELF_section_header_sym %ELF_shstr__sym>ELF_shstr # sh_name -## FIXME: using type 03 (strtab) makes objdump -d happier -## using type 02 make readelf complain but display valid symbol table -# 03 00 00 00 # sh_type: str-sht-symtab 02 00 00 00 # sh_type: str-sht-symtab 00 00 00 00 00 00 00 00 # sh_flags &ELF_sym 00 00 00 00 # sh_addr @@ -190,8 +189,8 @@ %ELF_end>ELF_sym 00 00 00 00 # sh_length 06 00 00 00 # sh_link:6 00 00 00 00 # sh_info -00 00 00 00 00 00 00 00 # sh_1? -40 00 00 00 00 00 00 00 # sh_entsize +01 00 00 00 00 00 00 00 # sh_1? +18 00 00 00 00 00 00 00 # sh_entsize :ELF_section_header_str %ELF_shstr__str>ELF_shstr # sh_name diff --git a/lib/x86_64-mes/x86_64.M1 b/lib/x86_64-mes/x86_64.M1 new file mode 100644 index 00000000..4178160e --- /dev/null +++ b/lib/x86_64-mes/x86_64.M1 @@ -0,0 +1,50 @@ +### GNU Mes --- Maxwell Equations of Software +### Copyright © 2018 Jan (janneke) Nieuwenhuizen +### +### This file is part of GNU Mes. +### +### Mes is free software# you can redistribute it and/or modify it +### under the terms of the GNU General Public License as published by +### the Free Software Foundation# either version 3 of the License, or (at +### your option) any later version. +### +### GNU Mes is distributed in the hope that it will be useful, but +### WITHOUT ANY WARRANTY# without even the implied warranty of +### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +### GNU General Public License for more details. +### +### You should have received a copy of the GNU General Public License +### along with GNU Mes. If not, see . + +DEFINE add____$i8,%rax 4883c0 +DEFINE add____%rbp,%rax 4801e8 +DEFINE call32 e8 +DEFINE hlt f4 +DEFINE mov____$i32,%rax 48c7c0 +DEFINE mov____$i32,0x8(%rbp) c745 +DEFINE mov____$i64,%rax 48a1 +DEFINE mov____%edi,0x8(%rbp) 897d +DEFINE mov____%r8,0x8(%rbp) 4c8945 +DEFINE mov____%rax,%rax 4889c0 +DEFINE mov____%rax,%rbx 4889c3 +DEFINE mov____%rax,%rdi 4889c7 +DEFINE mov____%rax,%rsi 4889c6 +DEFINE mov____%rax,0x8(%rbp) 488945 +DEFINE mov____%rbp,%rax 4889e8 +DEFINE mov____%rbp,%rsp 4889ec +DEFINE mov____%rcx,0x8(%rbp) 48894d +DEFINE mov____%rdi,0x8(%rbp) 48897d +DEFINE mov____%rdx,0x8(%rbp) 488955 +DEFINE mov____%rsi,0x8(%rbp) 488975 +DEFINE mov____%rsp,%rbp 4889e5 +DEFINE mov____(%rax),%rax 488b00 +DEFINE mov____0x8(%rbp),%eax 8b45 +DEFINE mov____0x8(%rbp),%rax 488b45 +DEFINE nop 90 +DEFINE pop____%rbp 5d +DEFINE push___%rbp 55 +DEFINE ret c3 +DEFINE shl____$i8,%rax 48c1e0 +DEFINE sub____$i32,%rsp 4881ec +DEFINE syscall 0f05 +DEFINE test___%rax,%rax 4885c0 diff --git a/mes/module/mescc/i386/as.mes b/mes/module/mescc/i386/as.mes index f1c97a28..c65bbcb4 100644 --- a/mes/module/mescc/i386/as.mes +++ b/mes/module/mescc/i386/as.mes @@ -19,4 +19,5 @@ ;;; along with GNU Mes. If not, see . (mes-use-module (mescc as)) +(mes-use-module (mescc info)) (include-from-path "mescc/i386/as.scm") diff --git a/mes/module/mescc/i386/info.mes b/mes/module/mescc/i386/info.mes new file mode 100644 index 00000000..47a502dc --- /dev/null +++ b/mes/module/mescc/i386/info.mes @@ -0,0 +1,23 @@ +;;; -*-scheme-*- + +;;; GNU Mes --- Maxwell Equations of Software +;;; Copyright © 2018 Jan (janneke) Nieuwenhuizen +;;; +;;; This file is part of GNU Mes. +;;; +;;; GNU Mes is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Mes is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Mes. If not, see . + +(mes-use-module (mescc info)) +(mes-use-module (mescc i386 as)) +(include-from-path "mescc/i386/info.scm") diff --git a/mes/module/mescc/mescc.mes b/mes/module/mescc/mescc.mes index 6e8c9a04..87370887 100644 --- a/mes/module/mescc/mescc.mes +++ b/mes/module/mescc/mescc.mes @@ -23,8 +23,10 @@ (mes-use-module (srfi srfi-26)) (mes-use-module (mes misc)) (mes-use-module (mes getopt-long)) - (mes-use-module (mes guile)) + +(mes-use-module (mescc i386 info)) +(mes-use-module (mescc x86_64 info)) (mes-use-module (mescc preprocess)) (mes-use-module (mescc compile)) (mes-use-module (mescc M1)) diff --git a/mes/module/mescc/x86_64/as.mes b/mes/module/mescc/x86_64/as.mes new file mode 100644 index 00000000..e83f3f62 --- /dev/null +++ b/mes/module/mescc/x86_64/as.mes @@ -0,0 +1,23 @@ +;;; -*-scheme-*- + +;;; GNU Mes --- Maxwell Equations of Software +;;; Copyright © 2018 Jan (janneke) Nieuwenhuizen +;;; +;;; This file is part of GNU Mes. +;;; +;;; GNU Mes is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Mes is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Mes. If not, see . + +(mes-use-module (mescc as)) +(mes-use-module (mescc info)) +(include-from-path "mescc/x86_64/as.scm") diff --git a/mes/module/mescc/x86_64/info.mes b/mes/module/mescc/x86_64/info.mes new file mode 100644 index 00000000..d86ea013 --- /dev/null +++ b/mes/module/mescc/x86_64/info.mes @@ -0,0 +1,23 @@ +;;; -*-scheme-*- + +;;; GNU Mes --- Maxwell Equations of Software +;;; Copyright © 2018 Jan (janneke) Nieuwenhuizen +;;; +;;; This file is part of GNU Mes. +;;; +;;; GNU Mes is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Mes is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Mes. If not, see . + +(mes-use-module (mescc info)) +(mes-use-module (mescc x86_64 as)) +(include-from-path "mescc/x86_64/info.scm") diff --git a/module/mescc/as.scm b/module/mescc/as.scm index af63d3b3..b2e650d0 100644 --- a/module/mescc/as.scm +++ b/module/mescc/as.scm @@ -20,7 +20,9 @@ #:use-module (srfi srfi-1) #:use-module (mes guile) #:use-module (mescc bytevectors) - #:export (dec->hex + #:use-module (mescc info) + #:export (as + dec->hex int->bv8 int->bv16 int->bv32)) @@ -44,3 +46,7 @@ (cond ((number? o) (number->string o 16)) ((char? o) (number->string (char->integer o) 16)) (else (format #f "~s" o)))) + +(define (as info instruction . rest) + (let ((proc (assoc-ref (.instructions info) instruction))) + (apply proc info rest))) diff --git a/module/mescc/compile.scm b/module/mescc/compile.scm index ce7b98e4..e57541d6 100644 --- a/module/mescc/compile.scm +++ b/module/mescc/compile.scm @@ -551,6 +551,32 @@ (define (number->accu o) (wrap-as (i386:value->accu o))) +(define (ident->r0 info) + (lambda (o) + (cond ((assoc-ref (.locals info) o) => (cut local->r0 info <>)) + + ((assoc-ref (.statics info) o) => global->accu) + ((assoc-ref (filter (negate static-global?) (.globals info)) o) => global->accu) + ((assoc-ref (.constants info) o) => number->accu) + (else (list (i386:label->accu `(#:address ,o)))) + + + ;; ((assoc-ref (.statics info) o) => (cut global->r0 info <>)) + ;; ((assoc-ref (filter (negate static-global?) (.globals info)) o) => (cut global->r0 info <>)) + ;; ((assoc-ref (.constants info) o) => (cut number->r0 info <>)) + ;; (else (wrap-as (as info 'label->r0 `(#:address ,o)))) + ))) + +(define (local->r0 info o) + (let* ((type (local:type o))) + (cond ((or (c-array? type) + (structured-type? type)) + ;;(wrap-as (as info 'local-ptr->r0 (local:id o))) + (wrap-as (i386:local-ptr->accu (local:id o))) + ) + (else (append (wrap-as (as info 'local->r0 (local:id o))) + (convert-r0 info type)))))) + (define (ident-address->accu info) (lambda (o) (cond ((assoc-ref (.locals info) o) @@ -602,6 +628,26 @@ (if (<= size 4) (wrap-as (i386:accu->label global)) (wrap-as (i386:accu*n->label global size))))))))) +(define (r0->ident info) + (lambda (o) + (cond ((assoc-ref (.locals info) o) + => + (lambda (local) (let ((size (->size local))) + (if (<= size 4) (wrap-as (as info 'r0->local (local:id local))) + (wrap-as (i386:accu*n->local (local:id local) size)) + ;;(wrap-as (as info 'r0*n->local (local:id local) size)) + )))) + ((assoc-ref (.statics info) o) + => + (lambda (global) (let ((size (->size global))) + (if (<= size 4) (wrap-as (i386:accu->label global)) + (wrap-as (i386:accu*n->label global size)))))) + ((assoc-ref (filter (negate static-global?) (.globals info)) o) + => + (lambda (global) (let ((size (->size global))) + (if (<= size 4) (wrap-as (i386:accu->label global)) + (wrap-as (i386:accu*n->label global size))))))))) + (define (value->ident info) (lambda (o value) (cond ((assoc-ref (.locals info) o) @@ -706,13 +752,50 @@ (define (alloc-register info) (let ((registers (.registers info))) - (stderr " =>register: ~a\n" (car registers)) - (clone info #:allocated (cons (car registers) (.allocated info)) #:registers (cdr registers)))) + ;; (stderr "\nalloc-register") + ;; (stderr " allocated: ~s\n" (.allocated info)) + ;; (stderr " =>registers: ~s\n" registers) + ;; (stderr " =>register: ~s\n" (car registers)) + ;; (clone info #:allocated (cons (car registers) (.allocated info)) #:registers (cdr registers)) + info + )) (define (free-register info) (let ((allocated (.allocated info))) - (stderr " <=register: ~a\n" (car allocated)) - (clone info #:allocated (cdr allocated) #:registers (cons (car allocated) (.registers info))))) + ;; (stderr " <=register: ~a\n" (car allocated)) + ;; (clone info #:allocated (cdr allocated) #:registers (cons (car allocated) (.registers info))) + info + )) + +(define (r0->r1-mem*n- info n) + (wrap-as + (case n + ((1) (as info 'byte-r0->r1-mem)) + ((2) (as info 'word-r0->r1-mem)) + ((4) (as info 'int-r0->r1-mem)) + ((8) (as info 'quad-r0->r1-mem)) + (else (append (let loop ((i 0)) + (if (>= i n) '() + (append (if (= i 0) '() + (append (i386:accu+value 4) + (i386:base+value 4))) + (case (- n i) + ((1) (append (i386:accu+value -3) + (i386:base+value -3) + (i386:accu-mem->base-mem))) + ((2) (append (i386:accu+value -2) + (i386:base+value -2) + (i386:accu-mem->base-mem))) + ((3) (append (i386:accu+value -1) + (i386:base+value -1) + (i386:accu-mem->base-mem))) + (else (i386:accu-mem->base-mem))) + (loop (+ i 4)))))))))) + +(define (r0->r1-mem*n info n) + ;;(append-text info (r0->r1-mem*n- info n)) + (append-text info (accu->base-mem*n- info n)) + ) (define (expr->register* o info) @@ -852,7 +935,7 @@ info))) (define (expr->register o info) - (stderr "expr->register o=~s\n" o) + ;;(stderr "expr->register o=~s\n" o) (let ((locals (.locals info)) (text (.text info)) @@ -882,7 +965,7 @@ ((p-expr (fixed ,value)) (let ((value (cstring->int value)) (info (alloc-register info))) - (append-text info (wrap-as (i386:value->accu value))))) + (append-text info (wrap-as (as info 'value->r0 value))))) ((p-expr (float ,value)) (let ((value (cstring->float value))) @@ -899,7 +982,7 @@ (,char (guard (char? char)) (append-text info (wrap-as (i386:value->accu char)))) ((p-expr (ident ,name)) - (append-text info ((ident->accu info) name))) + (append-text info ((ident->r0 info) name))) ((initzer ,initzer) (expr->register initzer info)) @@ -973,7 +1056,7 @@ (not (assoc name globals)) (not (equal? name (.function info)))) (stderr "warning: undeclared function: ~a\n" name)) - (append-text args-info (list (i386:call-label name n)))) + (append-text args-info (wrap-as (as info 'call-label name n)))) (let* ((empty (clone info #:text '())) (accu (expr->register `(p-expr (ident ,name)) empty))) (append-text args-info (append (.text accu) @@ -1206,7 +1289,6 @@ (append-text info ((ident-add info) name (- size))))) ((assn-expr ,a (op ,op) ,b) - (stderr "ASSN!\n") (let* ((info (append-text info (ast->comment o))) (type (ast->type a info)) (rank (->rank type)) @@ -1252,14 +1334,13 @@ (or (= size-b 1) (= size-b 2))))) (stderr "ERROR assign: ~a" (with-output-to-string (lambda () (pretty-print-c99 o)))) (stderr " size[~a]:~a != size[~a]:~a\n" rank size rank-b size-b)) - (stderr " assign a=~s\n" a) (pmatch a ((p-expr (ident ,name)) (if (or (<= size 4) ;; FIXME: long long = int - (<= size-b 4)) (append-text info ((accu->ident info) name)) - (let* ((info (expr->base* a info)) - (info (accu->base-mem*n info size))) - ;;??? + (<= size-b 4)) (append-text info ((r0->ident info) name)) + (let* (;;(info (expr->register* a info)) + (info (expr->base* a info)) + (info (r0->r1-mem*n info size))) (free-register info)))) (_ (let* ((info (expr->base* a info)) (info (if (not (bit-field? type)) info @@ -1312,6 +1393,20 @@ (wrap-as (i386:word-accu))) (else '()))))) +(define (convert-r0 info type) + (if (not (type? type)) '() + (let ((sign (signed? type)) + (size (->size type))) + (cond ((and (= size 1) sign) + (wrap-as (i386:signed-byte-accu))) + ((= size 1) + (wrap-as (i386:byte-accu))) + ((and (= size 2) sign) + (wrap-as (i386:signed-word-accu))) + ((= size 1) + (wrap-as (i386:word-accu))) + (else '()))))) + (define (expr->base o info) (let* ((info (append-text info (wrap-as (i386:push-accu)))) (info (expr->register o info)) @@ -1384,21 +1479,21 @@ 4))) ((jump (if (= size 1) i386:jump-byte-z i386:jump-z) - (wrap-as (i386:accu-zero?))) o))) + (wrap-as (as info 'r0-zero?))) o))) ((de-ref ,expr) (let* ((rank (expr->rank info expr)) (size (if (= rank 1) (ast-type->size info expr) 4))) ((jump (if (= size 1) i386:jump-byte-z i386:jump-z) - (wrap-as (i386:accu-zero?))) o))) + (wrap-as (as info 'r0-zero?))) o))) ((assn-expr (p-expr (ident ,name)) ,op ,expr) ((jump i386:jump-z (append ((ident->accu info) name) - (wrap-as (i386:accu-zero?)))) o)) + (wrap-as (as info 'r0-zero?)))) o)) - (_ ((jump i386:jump-z (wrap-as (i386:accu-zero?))) o))))) + (_ ((jump i386:jump-z (wrap-as (as info 'r0-zero?))) o))))) (define (cstring->int o) (let ((o (cond ((string-suffix? "ULL" o) (string-drop-right o 3)) @@ -1523,7 +1618,7 @@ (_ (error "ptr-declr->rank not supported: " o)))) (define (ast->info o info) - (stderr "ast->info o=~s\n" o) + ;; (stderr "ast->info o=~s\n" o) (let ((functions (.functions info)) (globals (.globals info)) (locals (.locals info)) @@ -1563,7 +1658,7 @@ (append-text info (wrap-as (asm->m1 arg0)))) (let* ((info (append-text info (ast->comment o))) (info (expr->register `(fctn-call (p-expr (ident ,name)) (expr-list . ,expr-list)) info))) - (append-text info (wrap-as (i386:accu-zero?)))))) + (append-text info (wrap-as (as info 'r0-zero?)))))) ((if ,test ,then) (let* ((info (append-text info (ast->comment `(if ,test (ellipsis))))) @@ -1719,7 +1814,7 @@ ((return ,expr) (let ((info (expr->register expr info))) - (append-text info (append (wrap-as (i386:ret)))))) + (append-text info (append (wrap-as (as info 'ret)))))) ((decl . ,decl) ;;FIXME: ridiculous performance hit with mes @@ -1740,13 +1835,13 @@ ;; EXPR ((expr-stmt ,expression) (let* ((info (expr->register expression info)) - (info (append-text info (wrap-as (i386:accu-zero?))))) + (info (append-text info (wrap-as (as info 'r0-zero?))))) (free-register info))) ;; FIXME: why do we get (post-inc ...) here ;; (array-ref (_ (let ((info (expr->register o info))) - (append-text info (wrap-as (i386:accu-zero?)))))))) + (append-text info (wrap-as (as info 'r0-zero?)))))))) (define (ast-list->info o info) (fold ast->info info o)) @@ -2344,13 +2439,13 @@ '() )) -(define (param-list->text o) +(define (param-list->text o info) (pmatch o ((param-list . ,formals) (let ((n (length formals))) - (wrap-as (append (i386:function-preamble) + (wrap-as (append (as info 'function-preamble formals) (append-map (formal->text n) formals (iota n)) - (i386:function-locals))))) + (as info 'function-locals))))) (_ (error "param-list->text: not supported: " o)))) (define (param-list->locals o info) @@ -2395,14 +2490,14 @@ (define (fctn-defn->info o info) (define (assert-return text) - (let ((return (wrap-as (i386:ret)))) + (let ((return (wrap-as (as info 'ret)))) (if (equal? (list-tail text (- (length text) (length return))) return) text (append text return)))) (let ((name (fctn-defn:get-name o))) (mescc:trace name) (let* ((type (fctn-defn:get-type info o)) (formals (fctn-defn:get-formals o)) - (text (param-list->text formals)) + (text (param-list->text formals info)) (locals (param-list->locals formals info)) (statement (fctn-defn:get-statement o)) (function (cons name (make-function name type '()))) diff --git a/module/mescc/i386/as.scm b/module/mescc/i386/as.scm index ffd02262..d617a0e8 100644 --- a/module/mescc/i386/as.scm +++ b/module/mescc/i386/as.scm @@ -25,6 +25,7 @@ (define-module (mescc i386 as) #:use-module (mes guile) #:use-module (mescc as) + #:use-module (mescc info) #:export ( i386:accu%base i386:accu*base @@ -86,8 +87,6 @@ i386:call-accu i386:call-label i386:formal - i386:function-locals - i386:function-preamble i386:jump i386:jump i386:jump-a @@ -134,7 +133,6 @@ i386:push-local i386:push-local-address i386:push-local-de-ref - i386:ret i386:ret-local i386:sub-base i386:test-base @@ -159,17 +157,19 @@ i386:signed-byte-accu i386:word-accu i386:signed-word-accu + + i386:instructions )) (define (i386:nop) '(("nop"))) -(define (i386:function-preamble) +(define (i386:function-preamble . rest) '(("push___%ebp") ("mov____%esp,%ebp"))) -(define (i386:function-locals) - `(("sub____%esp,$i32" (#:immediate ,(+ (* 4 1025) (* 20 4)))))) ; sub %esp,xxx 4*1024 buf, 20 local vars +(define (i386:function-locals . rest) + `(("sub____$i32,%esp" (#:immediate ,(+ (* 4 1025) (* 20 4)))))) ; 4*1024 buf, 20 local vars (define (i386:push-label label) `(("push___$i32" (#:address ,label)))) ; push $0x