#!/bin/sh

MACHINE=`uname -m`
if [ $MACHINE = i686 -o $MACHINE = i586 ]; then
  OS=`uname -o 2>/dev/null`
  if [ $? != 0 ]; then # -o option unrecognized
    OS=unknown
  fi
  if [ ! $OS = Cygwin ]; then
    OS=`uname -s`
  fi 
else
  OS=`uname -s`
fi

# TODO checks to allow valid machine / os combinations
# TODO check for existence of required linux commands

echo $MACHINE $OS

if [ $MACHINE = i686 -o $MACHINE = i586 -o $MACHINE = i386 -o $MACHINE = x86_64 -o $MACHINE = amd64 ]; then

  # increase stack size

  sed -e 's/STACK_SIZE 21000000/STACK_SIZE 22000000/g' \
    rt/rt-x86-src/rt.asm >rt.asm

  if [ $OS = Cygwin ]; then # windows
    RT_OS=rt/rt-x86-src/rt-win.asm
  elif [ $OS = FreeBSD ]; then
    RT_OS=rt/rt-x86-src/rt-freebsd64.asm
  elif [ $OS = OpenBSD ]; then
    RT_OS=rt/rt-x86-src/rt-openbsd32.asm
  elif [ $OS = Darwin ]; then # Mac OS X
    RT_OS=rt/rt-x86-src/rt-osx32.asm
  else # GNU/Linux
    RT_OS=rt/rt-x86-src/rt-linux.asm
  fi
  cat rt/rt-x86-src/rt-comment.asm \
      $RT_OS \
      rt.asm \
      src/asm/simpvir-x86-core.asm \
      >x.asm

  if [ $MACHINE = i686 -o $MACHINE = i586 -o $MACHINE = i386 ]; then # 32 bit
    sed -e 's/rax/eax/g' \
        -e 's/rsp/esp/g' \
      <x.asm >xx.asm
    mv xx.asm x.asm
    nasm -f elf32 -o zzz.o x.asm
    if [ $OS = Cygwin ]; then # windows
      gcc -o bin/simpvir zzz.o
    elif [ $OS = OpenBSD ]; then
      ld.bfd -nopie -static -o bin/simpvir zzz.o
    else # GNU/Linux or FreeBSD
      ld -s -o bin/simpvir zzz.o
    fi
  else # x86_64 or amd64
    if [ $OS = Darwin ]; then
      sed -e 's/rax/eax/g' \
          -e 's/rsp/esp/g' \
        <x.asm >xx.asm
      mv xx.asm x.asm
      ~/Downloads/nasm-2.11.08/nasm -f macho x.asm -o zzz.o
      ld -o bin/simpvir zzz.o
    else
      sed -e 's/push  eax/push  rax/g' \
          -e 's/pop   eax/pop   rax/g' \
          -e 's/push  ebx/push  rbx/g' \
          -e 's/pop   ebx/pop   rbx/g' \
          -e 's/push  ecx/push  rcx/g' \
          -e 's/pop   ecx/pop   rcx/g' \
          -e 's/push  edx/push  rdx/g' \
          -e 's/pop   edx/pop   rdx/g' \
          -e 's/push  edi/push  rdi/g' \
          -e 's/pop   edi/pop   rdi/g' \
          -e 's/push  esi/push  rsi/g' \
          -e 's/pop   esi/pop   rsi/g' \
          -e 's/rsp + 16/rsp + 32/g' \
          -e 's/rsp + 12/rsp + 24/g' \
          -e 's/rsp + 8/rsp + 16/g' \
          -e 's/rsp + 4/rsp + 8/g' \
          -e 's/rsp, 4/rsp, 8/g' \
          -e 's/rsp, 20/rsp, 40/g' \
        <x.asm >xx.asm
      mv xx.asm x.asm
      nasm -f elf64 -o zzz.o x.asm
      if [ $OS = FreeBSD ]; then
        cc -o bin/simpvir zzz.o # resolve calls to libc
      else
        ld -s -o bin/simpvir zzz.o
      fi
    fi
  fi

  rm rt.asm x.asm zzz.o
elif [ $MACHINE = armv6l ] || [ $MACHINE = armv7l ]; then

  # increase stack size

  sed -e 's/84000000/88000000/g' \
      -e 's/21000000/22000000/g' \
    rt/rt-arm-src/data.s >data.s

  if [ $MACHINE = armv6l ]; then
    ARM_MODE=arm6
  else
    ARM_MODE=arm7
  fi

  cp src/asm/simpvir-$ARM_MODE-core.s xxx.s

  cat xxx.s | sed -e 's/_-/_/g' >yyy.s # absolute value of -maxint is somehow neg
  rm xxx.s
  grep "@X@" yyy.s | sed -e 's/@X@//g' >global-defines.s

  cat data.s \
    global-defines.s \
    rt/rt-arm-src/text.s \
    rt/rt-arm-src/rt-linux.s \
    rt/rt-arm-src/rt.s \
    rt/rt-arm-src/start.s \
    rt/rt-arm-src/init.s \
    yyy.s \
    rt/rt-arm-src/cleanup.s >zzz.s

  if [ $MACHINE = arm6l ]; then
    as -march=armv6j -mfpu=vfp -mfloat-abi=hard --fatal-warnings \
      -o zzz.o zzz.s
  else
    as --fatal-warnings \
      -o zzz.o zzz.s
  fi
  ld zzz.o -o bin/simpvir

  rm -f rt.s yyy.s global-defines.s zzz.o
elif [ $MACHINE = riscv64 ]; then

  # set stack size

  sed -e "s/84000000/88000000/g" \
      -e "s/21000000/22000000/g" \
    rt/rt-riscv-src/data.s >data.s

  # TODO following update is temporary

  sed -e "s/84000000/88000000/g" \
    rt/rt-riscv-src/start.s >start.s

  cp src/asm/simpvir-riscv-core.s xxx.s

  # TODO do we need rt/rt-arm-src/init.s
  cat data.s \
    rt/rt-riscv-src/text.s \
    rt/rt-riscv-src/rt-linux.s \
    rt/rt-riscv-src/rt.s \
    start.s \
    xxx.s \
    rt/rt-riscv-src/cleanup.s >zzz.s

    as -o zzz.o zzz.s
  # ld zzz.o -o bin/simpvir
    ld zzz.o -o bin/simpvir -lc # TODO temporarily use C malloc from -lc

    rm -f xxx.s data.s start.s zzz.o
else
  echo "unsupported machine type:" $MACHINE
fi
