From: David Given Date: Thu, 16 May 2013 23:03:38 +0000 (+0100) Subject: Skeleton of VideoCore IV support for the Raspberry Pi. X-Git-Tag: release-6-0-pre-5~10^2~77 X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=32ebc502c86047797d72122a98e329f2ca03a05e;p=ack.git Skeleton of VideoCore IV support for the Raspberry Pi. --HG-- branch : dtrg-videocore rename : mach/powerpc/as/.distr => mach/vc4/as/.distr rename : mach/powerpc/as/mach0.c => mach/vc4/as/mach0.c rename : mach/powerpc/as/mach1.c => mach/vc4/as/mach1.c rename : mach/powerpc/as/mach2.c => mach/vc4/as/mach2.c rename : mach/powerpc/as/mach3.c => mach/vc4/as/mach3.c rename : mach/powerpc/as/mach4.c => mach/vc4/as/mach4.c rename : mach/powerpc/as/mach5.c => mach/vc4/as/mach5.c rename : mach/i86/build.mk => mach/vc4/build.mk rename : mach/powerpc/libem/powerpc.h => mach/vc4/libem/videocore.h rename : mach/i86/libend/.distr => mach/vc4/libend/.distr rename : mach/i86/libend/edata.s => mach/vc4/libend/edata.s rename : mach/i86/libend/em_end.s => mach/vc4/libend/em_end.s rename : mach/i86/libend/end.s => mach/vc4/libend/end.s rename : mach/i86/libend/etext.s => mach/vc4/libend/etext.s rename : mach/powerpc/ncg/.distr => mach/vc4/ncg/.distr rename : mach/powerpc/ncg/mach.c => mach/vc4/ncg/mach.c rename : mach/powerpc/ncg/mach.h => mach/vc4/ncg/mach.h rename : mach/powerpc/ncg/table => mach/vc4/ncg/table rename : plat/pc86/descr => plat/rpi/descr --- diff --git a/mach/vc4/as/.distr b/mach/vc4/as/.distr new file mode 100644 index 000000000..8ebe3797c --- /dev/null +++ b/mach/vc4/as/.distr @@ -0,0 +1,6 @@ +mach0.c +mach1.c +mach2.c +mach3.c +mach4.c +mach5.c diff --git a/mach/vc4/as/binary.h b/mach/vc4/as/binary.h new file mode 100644 index 000000000..c00e73550 --- /dev/null +++ b/mach/vc4/as/binary.h @@ -0,0 +1,34 @@ +/* + * VideoCore IV assembler for the ACK + * © 2013 David Given + * This file is redistributable under the terms of the 3-clause BSD license. + * See the file 'Copying' in the root of the distribution for the full text. + */ + +#ifndef BINARY_H +#define BINARY_H + +/* This grotesque nonsense allows us to use binary constants from C. */ + +#define HEX__(n) 0x##n##LU +#define B8__(x) \ + ((x&0x0000000FLU)?1:0) \ + +((x&0x000000F0LU)?2:0) \ + +((x&0x00000F00LU)?4:0) \ + +((x&0x0000F000LU)?8:0) \ + +((x&0x000F0000LU)?16:0) \ + +((x&0x00F00000LU)?32:0) \ + +((x&0x0F000000LU)?64:0) \ + +((x&0xF0000000LU)?128:0) + +#define B8(d) \ + ((unsigned char)B8__(HEX__(d))) +#define B16(dmsb,dlsb) \ + (((unsigned short)B8(dmsb)<<8) + B8(dlsb)) +#define B32(dmsb,db2,db3,dlsb) \ + (((unsigned long)B8(dmsb)<<24) \ + + ((unsigned long)B8(db2)<<16) \ + + ((unsigned long)B8(db3)<<8) \ + + B8(dlsb)) + +#endif diff --git a/mach/vc4/as/mach0.c b/mach/vc4/as/mach0.c new file mode 100644 index 000000000..b6294ecfc --- /dev/null +++ b/mach/vc4/as/mach0.c @@ -0,0 +1,31 @@ +/* + * VideoCore IV assembler for the ACK + * © 2013 David Given + * This file is redistributable under the terms of the 3-clause BSD license. + * See the file 'Copying' in the root of the distribution for the full text. + */ + +#define THREE_PASS /* branch and offset optimization */ +#define LISTING /* enable listing facilities */ +#define RELOCATION /* generate relocatable code */ +#define DEBUG 0 + +#undef valu_t +#define valu_t long + +#undef ADDR_T +#define ADDR_T long + +#undef word_t +#define word_t long + +#undef ALIGNWORD +#define ALIGNWORD 4 + +#undef ALIGNSECT +#define ALIGNSECT 4 + +#undef VALWIDTH +#define VALWIDTH 8 + +#define FIXUPFLAGS (RELBR | RELWR) diff --git a/mach/vc4/as/mach1.c b/mach/vc4/as/mach1.c new file mode 100644 index 000000000..96a8a07fa --- /dev/null +++ b/mach/vc4/as/mach1.c @@ -0,0 +1,6 @@ +/* + * VideoCore IV assembler for the ACK + * © 2013 David Given + * This file is redistributable under the terms of the 3-clause BSD license. + * See the file 'Copying' in the root of the distribution for the full text. + */ diff --git a/mach/vc4/as/mach2.c b/mach/vc4/as/mach2.c new file mode 100644 index 000000000..c69007de0 --- /dev/null +++ b/mach/vc4/as/mach2.c @@ -0,0 +1,22 @@ +/* + * VideoCore IV assembler for the ACK + * © 2013 David Given + * This file is redistributable under the terms of the 3-clause BSD license. + * See the file 'Copying' in the root of the distribution for the full text. + */ + +%token GPR + +%token OP +%token OP_ONEREG +%token OP_ONELREG +%token OP_ALU +%token OP_MEM +%token OP_BREG +%token OP_STACK + +/* Other token types */ + +/* %type c */ +%type e16 u8 u7 u6 u5 u4 u2 u1 +/* %type nb ds bda bdl lia lil */ diff --git a/mach/vc4/as/mach3.c b/mach/vc4/as/mach3.c new file mode 100644 index 000000000..b36652db7 --- /dev/null +++ b/mach/vc4/as/mach3.c @@ -0,0 +1,95 @@ +/* + * VideoCore IV assembler for the ACK + * © 2013 David Given + * This file is redistributable under the terms of the 3-clause BSD license. + * See the file 'Copying' in the root of the distribution for the full text. + */ + +#include "binary.h" + +/* Integer registers */ + +0, GPR, 0, "r0", +0, GPR, 1, "r1", +0, GPR, 2, "r2", +0, GPR, 3, "r3", +0, GPR, 4, "r4", +0, GPR, 5, "r5", + +0, GPR, 6, "r6", +0, GPR, 6, "fp", +0, GPR, 7, "r7", +0, GPR, 8, "r8", +0, GPR, 9, "r9", +0, GPR, 10, "r10", +0, GPR, 11, "r11", +0, GPR, 12, "r12", +0, GPR, 13, "r13", +0, GPR, 14, "r14", +0, GPR, 15, "r15", +0, GPR, 16, "r16", +0, GPR, 17, "r17", +0, GPR, 18, "r18", +0, GPR, 19, "r19", +0, GPR, 20, "r20", +0, GPR, 21, "r21", +0, GPR, 22, "r22", +0, GPR, 23, "r23", +0, GPR, 24, "r24", + +0, GPR, 25, "r25", +0, GPR, 25, "sp", +0, GPR, 26, "r26", +0, GPR, 26, "lr", +0, GPR, 27, "r27", +0, GPR, 28, "r28", +0, GPR, 29, "r29", +0, GPR, 30, "r30", +0, GPR, 30, "sr", +0, GPR, 31, "r31", +0, GPR, 31, "pc", + +/* Special instructions */ + +0, OP, B16(00000000,00000001), "nop", +0, OP, B16(00000000,00001010), "rti", + +0, OP_ONEREG, B16(00000000,01000000), "b", +0, OP_ONEREG, B16(00000000,01100000), "bl", +0, OP_ONELREG, B16(00000000,10000000), "tbb", +0, OP_ONELREG, B16(00000000,10100000), "tbs", + +0, OP_ALU, B8(00000000), "mov", +0, OP_ALU, B8(00000001), "cmn", +0, OP_ALU, B8(00000010), "add", +0, OP_ALU, B8(00000011), "bic", +0, OP_ALU, B8(00000100), "mul", +0, OP_ALU, B8(00000101), "eor", +0, OP_ALU, B8(00000110), "sub", +0, OP_ALU, B8(00000111), "and", +0, OP_ALU, B8(00001000), "mvn", +0, OP_ALU, B8(00001001), "ror", +0, OP_ALU, B8(00001010), "cmp", +0, OP_ALU, B8(00001011), "rsb", +0, OP_ALU, B8(00001100), "btst", +0, OP_ALU, B8(00001101), "or", +0, OP_ALU, B8(00001110), "extu", +0, OP_ALU, B8(00001111), "max", +0, OP_ALU, B8(00010000), "bset", +0, OP_ALU, B8(00010001), "min", +0, OP_ALU, B8(00010010), "bclr", +0, OP_ALU, B8(00010011), "adds2", +0, OP_ALU, B8(00010100), "bchg", +0, OP_ALU, B8(00010101), "adds4", +0, OP_ALU, B8(00010110), "adds8", +0, OP_ALU, B8(00010111), "adds16", +0, OP_ALU, B8(00011000), "exts", +0, OP_ALU, B8(00011001), "neg", +0, OP_ALU, B8(00011010), "lsr", +0, OP_ALU, B8(00011011), "clz", +0, OP_ALU, B8(00011100), "lsl", +0, OP_ALU, B8(00011101), "brev", +0, OP_ALU, B8(00011110), "asr", +0, OP_ALU, B8(00011111), "abs", + + diff --git a/mach/vc4/as/mach4.c b/mach/vc4/as/mach4.c new file mode 100644 index 000000000..d1320dae1 --- /dev/null +++ b/mach/vc4/as/mach4.c @@ -0,0 +1,110 @@ +/* + * VideoCore IV assembler for the ACK + * © 2013 David Given + * This file is redistributable under the terms of the 3-clause BSD license. + * See the file 'Copying' in the root of the distribution for the full text. + */ + +#include "binary.h" + +operation + : OP { emit2($1); } + + | OP_ONEREG GPR + { + emit2($1 | ($2<<0)); + } + + | OP_ONELREG GPR + { + if ($2 >= 0x10) + serror("cannot use r16+ here"); + emit2($1 | ($2<<0)); + } + + | OP_ALU GPR ',' GPR + { + emit2(B16(01000000, 00000000) | ($1<<8) | ($2<<0) | ($4<<4)); + } + + | OP_ALU GPR ',' '#' u5 + { + if ($1 >= 0x10) + serror("cannot use this ALU operation in 2op form"); + emit2(B16(01100000, 00000000) | ($1<<9) | ($2<<0) | ($5<<4)); + } + ; + +e16 + : expr + { + DOTVAL += 2; + newrelo($1.typ, RELO2 | FIXUPFLAGS); + DOTVAL -= 2; + $$ = $1.val & 0xFFFF; + } + ; + +u8 + : absexp + { + if (($1 < 0) || ($1 > 0xFF)) + serror("8-bit unsigned value out of range"); + $$ = $1; + } + ; + +u7 + : absexp + { + if (($1 < 0) || ($1 > 0x7F)) + serror("7-bit unsigned value out of range"); + $$ = $1; + } + ; + +u6 + : absexp + { + if (($1 < 0) || ($1 > 0x3F)) + serror("6-bit unsigned value out of range"); + $$ = $1; + } + ; + +u5 + : absexp + { + if (($1 < 0) || ($1 > 0x1F)) + serror("5-bit unsigned value out of range"); + $$ = $1; + } + ; + +u4 + : absexp + { + if (($1 < 0) || ($1 > 0xF)) + serror("4-bit unsigned value out of range"); + $$ = $1; + } + ; + +u1 + : absexp + { + if (($1 < 0) || ($1 > 1)) + serror("1-bit unsigned value out of range"); + $$ = $1; + } + ; + +u2 + : absexp + { + if (($1 < 0) || ($1 > 0x3)) + serror("2-bit unsigned value out of range"); + $$ = $1; + } + ; + diff --git a/mach/vc4/as/mach5.c b/mach/vc4/as/mach5.c new file mode 100644 index 000000000..668f4b748 --- /dev/null +++ b/mach/vc4/as/mach5.c @@ -0,0 +1,7 @@ +/* + * VideoCore IV assembler for the ACK + * © 2013 David Given + * This file is redistributable under the terms of the 3-clause BSD license. + * See the file 'Copying' in the root of the distribution for the full text. + */ + diff --git a/mach/vc4/build.mk b/mach/vc4/build.mk new file mode 100644 index 000000000..06ea3edd4 --- /dev/null +++ b/mach/vc4/build.mk @@ -0,0 +1,10 @@ +arch-libem-vc4 := \ + dummy.s + +arch-libend-vc4 = \ + edata.s \ + em_end.s \ + end.s \ + etext.s + + diff --git a/mach/vc4/libem/dummy.s b/mach/vc4/libem/dummy.s new file mode 100644 index 000000000..4edaa030f --- /dev/null +++ b/mach/vc4/libem/dummy.s @@ -0,0 +1,9 @@ +# +/* + * VideoCore IV support library for the ACK + * © 2013 David Given + * This file is redistributable under the terms of the 3-clause BSD license. + * See the file 'Copying' in the root of the distribution for the full text. + */ + +#include "videocore.h" diff --git a/mach/vc4/libem/videocore.h b/mach/vc4/libem/videocore.h new file mode 100644 index 000000000..3e27a7e7b --- /dev/null +++ b/mach/vc4/libem/videocore.h @@ -0,0 +1,15 @@ +# +/* + * VideoCore IV support library for the ACK + * © 2013 David Given + * This file is redistributable under the terms of the 3-clause BSD license. + * See the file 'Copying' in the root of the distribution for the full text. + */ + +! Declare segments (the order is important). + +.sect .text +.sect .rom +.sect .data +.sect .bss + diff --git a/mach/vc4/libend/.distr b/mach/vc4/libend/.distr new file mode 100644 index 000000000..afa027b6e --- /dev/null +++ b/mach/vc4/libend/.distr @@ -0,0 +1,4 @@ +edata.s +em_end.s +end.s +etext.s diff --git a/mach/vc4/libend/edata.s b/mach/vc4/libend/edata.s new file mode 100644 index 000000000..e706877db --- /dev/null +++ b/mach/vc4/libend/edata.s @@ -0,0 +1,15 @@ +# +/* + * VideoCore IV support library for the ACK + * © 2013 David Given + * This file is redistributable under the terms of the 3-clause BSD license. + * See the file 'Copying' in the root of the distribution for the full text. + */ + +.sect .text +.sect .rom +.sect .data +.sect .bss +.define _edata +.sect .data +_edata: diff --git a/mach/vc4/libend/em_end.s b/mach/vc4/libend/em_end.s new file mode 100644 index 000000000..bae5aaa0c --- /dev/null +++ b/mach/vc4/libend/em_end.s @@ -0,0 +1,24 @@ +# +/* + * VideoCore IV support library for the ACK + * © 2013 David Given + * This file is redistributable under the terms of the 3-clause BSD license. + * See the file 'Copying' in the root of the distribution for the full text. + */ + +.sect .text +.sect .rom +.sect .data +.sect .bss +.sect .end ! only for declaration of _end, __end and endbss. +.define endtext, endrom, enddata, endbss, __end + + .sect .text +endtext: + .sect .rom +endrom: + .sect .data +enddata: + .sect .end +__end: +endbss: diff --git a/mach/vc4/libend/end.s b/mach/vc4/libend/end.s new file mode 100644 index 000000000..5ce2882b6 --- /dev/null +++ b/mach/vc4/libend/end.s @@ -0,0 +1,15 @@ +# +/* + * VideoCore IV support library for the ACK + * © 2013 David Given + * This file is redistributable under the terms of the 3-clause BSD license. + * See the file 'Copying' in the root of the distribution for the full text. + */ + +.sect .text +.sect .rom +.sect .data +.sect .bss +.define _end +.sect .end ! only for declaration of _end, __end and endbss. +_end: diff --git a/mach/vc4/libend/etext.s b/mach/vc4/libend/etext.s new file mode 100644 index 000000000..973ab1814 --- /dev/null +++ b/mach/vc4/libend/etext.s @@ -0,0 +1,15 @@ +# +/* + * VideoCore IV support library for the ACK + * © 2013 David Given + * This file is redistributable under the terms of the 3-clause BSD license. + * See the file 'Copying' in the root of the distribution for the full text. + */ + +.sect .text +.sect .rom +.sect .data +.sect .bss +.define _etext +.sect .text +_etext: diff --git a/mach/vc4/ncg/.distr b/mach/vc4/ncg/.distr new file mode 100644 index 000000000..ccdf9bf7e --- /dev/null +++ b/mach/vc4/ncg/.distr @@ -0,0 +1,3 @@ +mach.c +mach.h +table diff --git a/mach/vc4/ncg/mach.c b/mach/vc4/ncg/mach.c new file mode 100644 index 000000000..f57a2a08f --- /dev/null +++ b/mach/vc4/ncg/mach.c @@ -0,0 +1,210 @@ +/* + * VideoCore IV code generator for the ACK + * © 2013 David Given + * This file is redistributable under the terms of the 3-clause BSD license. + * See the file 'Copying' in the root of the distribution for the full text. + */ + +#include +#include + +#ifndef NORCSID +static char rcsid[]= "$Id$" ; +#endif + +int framesize; + +/* + * machine dependent back end routines for the Zilog Z80. + */ + +con_part(int sz, word w) +{ + while (part_size % sz) + part_size++; + if (part_size == TEM_WSIZE) + part_flush(); + if (sz == 1) { + w &= 0xFF; + w <<= 8*(3-part_size); + part_word |= w; + } else if (sz == 2) { + w &= 0xFFFF; + if (part_size == 0) { + /* Shift 8 for m68k2, 16 otherwise */ + w <<= 4 * TEM_WSIZE; + } + part_word |= w; + } else { + assert(sz == TEM_WSIZE); + part_word = w; + } + part_size += sz; +} + +con_mult(word sz) +{ + + if (argval != 4) + fatal("bad icon/ucon size"); + fprintf(codefile,".data4 %s\n", str); +} + +#define CODE_GENERATOR +#define IEEEFLOAT +#define FL_MSL_AT_LOW_ADDRESS 1 +#define FL_MSW_AT_LOW_ADDRESS 1 +#define FL_MSB_AT_LOW_ADDRESS 1 +#include + +prolog(full nlocals) +{ + int ss = nlocals + 8; + fprintf(codefile, "addi sp, sp, %d\n", -ss); + fprintf(codefile, "stw fp, %d(sp)\n", nlocals); + fprintf(codefile, "mfspr r0, lr\n" + "stw r0, %d(sp)\n", nlocals+4); + fprintf(codefile, "addi fp, sp, %d\n", nlocals); + + framesize = nlocals; +} + +mes(word type) +{ + int argt ; + + switch ( (int)type ) { + case ms_ext : + for (;;) { + switch ( argt=getarg( + ptyp(sp_cend)|ptyp(sp_pnam)|sym_ptyp) ) { + case sp_cend : + return ; + default: + strarg(argt) ; + fprintf(codefile,".define %s\n",argstr) ; + break ; + } + } + default : + while ( getarg(any_ptyp) != sp_cend ) ; + break ; + } +} + +char *segname[] = { + ".sect .text", + ".sect .data", + ".sect .rom", + ".sect .bss" +}; + +#ifdef REGVARS + +static int savedregsi[32]; +static int numsaved; + +/* Initialise regvar system for one function. */ + +i_regsave() +{ + int i; + + fprintf(codefile, "! i_regsave()\n"); + for (i=0; i<32; i++) + savedregsi[i] = INT_MAX; + numsaved = 0; +} + +/* Mark a register as being saved. */ + +regsave(const char* regname, full offset, int size) +{ + int regnum = atoi(regname+1); + savedregsi[regnum] = offset; + numsaved++; + + fprintf(codefile, "! %d is saved in %s\n", offset, regname); +#if 0 + fprintf(codefile, "stwu %s, -4(sp)\n", regname); + if (offset >= 0) + fprintf(codefile, "lwz %s, %d(fp)\n", regname, offset); +#endif +} + +/* Finish saving ragisters. */ + +void saveloadregs(const char* ops, const char* opm) +{ + int offset = -(framesize + numsaved*4); + int reg = 32; + + /* Check for the possibility of a multiple. */ + + do + { + reg--; + } + while ((reg > 0) && (savedregsi[reg] != INT_MAX)); + if (reg < 31) + { + fprintf(codefile, "%s r%d, %d(fp)\n", opm, reg+1, offset); + offset += (31-reg)*4; + } + + /* Saved everything else singly. */ + + while (reg > 0) + { + if (savedregsi[reg] != INT_MAX) + { + fprintf(codefile, "%s r%d, %d(fp)\n", ops, reg, offset); + offset += 4; + } + reg--; + } +} + +f_regsave() +{ + int i; + fprintf(codefile, "! f_regsave()\n"); + fprintf(codefile, "addi sp, sp, %d\n", -numsaved*4); + + saveloadregs("stw", "stmw"); + + for (i=0; i<32; i++) + if ((savedregsi[i] != INT_MAX) && (savedregsi[i] > 0)) + fprintf(codefile, "lwz r%d, %d(fp)\n", i, savedregsi[i]); +} + +/* Restore all saved registers. */ + +regreturn() +{ + fprintf(codefile, "! regreturn()\n"); + saveloadregs("lwz", "lmw"); +} + +/* Calculate the score of a given register. */ + +int regscore(full offset, int size, int type, int frequency, int totype) +{ + int score; + + fprintf(codefile, "! regscore(%ld, %d, %d, %d, %d)\n", offset, size, type, frequency, totype); + + if (size != 4) + return -1; + + /* Per use: 6 bytes (on average) + * Overhead in prologue: 4 bytes, plus 4 if a parameter + * Overhead in epilogue: 0 bytes + */ + + score = frequency*6 - 4 - ((offset>=0) ? 4 : 0); + fprintf(codefile, "! local at offset %d has regvar score %d\n", offset, score); + return score; +} + +#endif diff --git a/mach/vc4/ncg/mach.h b/mach/vc4/ncg/mach.h new file mode 100644 index 000000000..89d2b8a97 --- /dev/null +++ b/mach/vc4/ncg/mach.h @@ -0,0 +1,32 @@ +/* + * VideoCore IV code generator for the ACK + * © 2013 David Given + * This file is redistributable under the terms of the 3-clause BSD license. + * See the file 'Copying' in the root of the distribution for the full text. + */ + +#define ex_ap(y) fprintf(codefile,".extern %s\n",y) +#define in_ap(y) /* nothing */ + +#define newilb(x) fprintf(codefile,"%s:\n",x) +#define newdlb(x) fprintf(codefile,"%s:\n",x) +#define dlbdlb(x,y) fprintf(codefile,"%s = %s\n",x,y) +#define newlbss(l,x) fprintf(codefile,".comm %s,%u\n",l,x); + +#define cst_fmt "%d" +#define off_fmt "%d" +#define ilb_fmt "I%x_%x" +#define dlb_fmt "_%d" +#define hol_fmt "hol%d" + +#define hol_off "%ld+hol%d" + +#define con_cst(x) fprintf(codefile,".data4\t%ld\n",x) +#define con_ilb(x) fprintf(codefile,".data4\t%s\n",x) +#define con_dlb(x) fprintf(codefile,".data4\t%s\n",x) + +#define fmt_id(sf, st) sprintf(st,"_%s",sf) + +#define modhead ".sect .text; .sect .rom; .sect .data; .sect .bss\n" + +#define BSS_INIT 0 diff --git a/mach/vc4/ncg/table b/mach/vc4/ncg/table new file mode 100644 index 000000000..f08ec3500 --- /dev/null +++ b/mach/vc4/ncg/table @@ -0,0 +1,1999 @@ +/* + * VideoCore IV code generator for the ACK + * © 2013 David Given + * This file is redistributable under the terms of the 3-clause BSD license. + * See the file 'Copying' in the root of the distribution for the full text. + */ + +EM_WSIZE = 4 +EM_PSIZE = 4 +EM_BSIZE = 8 /* two words saved in call frame */ + +INT8 = 1 /* Size of values */ +INT16 = 2 +INT32 = 4 +INT64 = 8 + +FP_OFFSET = 0 /* Offset of saved FP relative to our FP */ +PC_OFFSET = 4 /* Offset of saved PC relative to our FP */ + +#define COMMENT(n) /* noop */ + + +#define nicesize(x) ((x)==INT8 || (x)==INT16 || (x)==INT32 || (x)==INT64) + +#define smalls(n) sfit(n, 16) +#define smallu(n) ufit(n, 16) + +#define lo(n) (n & 0xFFFF) +#define hi(n) ((n>>16) & 0xFFFF) + +/* Use these for instructions that treat the low half as signed --- his() + * includes a modifier to produce the correct value when the low half gets + * sign extended. Er, do make sure you load the low half second. */ +#define los(n) (n & 0xFFFF) +#define his(n) ((hi(n) - (lo(n)>>15)) & 0xFFFF) + +#define IFFALSE {CONST, 4} +#define IFTRUE {CONST, 12} +#define ALWAYS {CONST, 20} +#define DCTRZ {CONST, 34} + +#define LT {CONST, 0} +#define GT {CONST, 1} +#define EQ {CONST, 2} + + + +PROPERTIES + + GPR /* any GPR */ + REG /* any allocatable GPR */ + FPR /* any FPR */ + FREG /* any allocatable FPR */ + SPR /* any SPR */ + CR /* any CR */ + + GPR0 GPRSP GPRFP GPR3 GPR4 GPR5 GPR6 GPR7 + GPR8 GPR9 GPR10 GPR11 GPR12 GPR13 GPR14 GPR15 + GPR16 GPR17 GPR18 GPR19 GPR20 GPR21 GPR22 GPR23 + GPR24 GPR25 GPR26 GPR27 GPR28 GPR29 GPR30 GPR31 + + CR0 CR1 + + FPR0 FPR1 FPR2 FPR3 FPR4 FPR5 FPR6 FPR7 + FPR8 FPR9 FPR10 FPR11 FPR12 FPR13 FPR14 FPR15 + FPR16 FPR17 FPR18 FPR19 FPR20 FPR21 FPR22 FPR23 + FPR24 FPR25 FPR26 FPR27 FPR28 FPR29 FPR30 FPR31 + +REGISTERS + + /* Reverse order to encourage ncg to allocate them from r31 down */ + + R31("r31") : GPR, REG, GPR31 regvar. + R30("r30") : GPR, REG, GPR30 regvar. + R29("r29") : GPR, REG, GPR29 regvar. + R28("r28") : GPR, REG, GPR28 regvar. + R27("r27") : GPR, REG, GPR27 regvar. + R26("r26") : GPR, REG, GPR26 regvar. + R25("r25") : GPR, REG, GPR25 regvar. + R24("r24") : GPR, REG, GPR24 regvar. + R23("r23") : GPR, REG, GPR23 regvar. + R22("r22") : GPR, REG, GPR22 regvar. + R21("r21") : GPR, REG, GPR21 regvar. + R20("r20") : GPR, REG, GPR20 regvar. + R19("r19") : GPR, REG, GPR19 regvar. + R18("r18") : GPR, REG, GPR18 regvar. + R17("r17") : GPR, REG, GPR17 regvar. + R16("r16") : GPR, REG, GPR16 regvar. + R15("r15") : GPR, REG, GPR15 regvar. + R14("r14") : GPR, REG, GPR14 regvar. + R13("r13") : GPR, REG, GPR13 regvar. + R12("r12") : GPR, REG, GPR12. + R11("r11") : GPR, GPR11. + R10("r10") : GPR, REG, GPR10. + R9("r9") : GPR, REG, GPR9. + R8("r8") : GPR, REG, GPR8. + R7("r7") : GPR, REG, GPR7. + R6("r6") : GPR, REG, GPR6. + R5("r5") : GPR, REG, GPR5. + R4("r4") : GPR, REG, GPR4. + R3("r3") : GPR, REG, GPR3. + FP("fp") : GPR, GPRFP. + SP("sp") : GPR, GPRSP. + R0("r0") : GPR, GPR0. + + F31("f31") : FPR, FREG, FPR31. + F30("f30") : FPR, FREG, FPR30. + F29("f29") : FPR, FREG, FPR29. + F28("f28") : FPR, FREG, FPR28. + F27("f27") : FPR, FREG, FPR27. + F26("f26") : FPR, FREG, FPR26. + F25("f25") : FPR, FREG, FPR25. + F24("f24") : FPR, FREG, FPR24. + F23("f23") : FPR, FREG, FPR23. + F22("f22") : FPR, FREG, FPR22. + F21("f21") : FPR, FREG, FPR21. + F20("f20") : FPR, FREG, FPR20. + F19("f19") : FPR, FREG, FPR19. + F18("f18") : FPR, FREG, FPR18. + F17("f17") : FPR, FREG, FPR17. + F16("f16") : FPR, FREG, FPR16. + F15("f15") : FPR, FREG, FPR15. + F14("f14") : FPR, FREG, FPR14. + F13("f13") : FPR, FREG, FPR13. + F12("f12") : FPR, FREG, FPR12. + F11("f11") : FPR, FREG, FPR11. + F10("f10") : FPR, FREG, FPR10. + F9("f9") : FPR, FREG, FPR9. + F8("f8") : FPR, FREG, FPR8. + F7("f7") : FPR, FREG, FPR7. + F6("f6") : FPR, FREG, FPR6. + F5("f5") : FPR, FREG, FPR5. + F4("f4") : FPR, FREG, FPR4. + F3("f3") : FPR, FREG, FPR3. + F2("f2") : FPR, FREG, FPR2. + F1("f1") : FPR, FREG, FPR1. + F0("f0") : FPR, FREG, FPR0. + + LR("lr") : SPR. + CTR("ctr") : SPR. + C0("cr0") : CR, CR0. + +#define SCRATCH R11 +#define FSCRATCH F0 + + +TOKENS + +/* Used only in instruction descriptions (to generate the correct syntax). */ + + GPRINDIRECT = { GPR reg; INT off; } 4 off "(" reg ")". + GPRINDIRECTLO = { GPR reg; ADDR adr; } 4 ">" adr "(" reg ")". /* Warning! Do not use on labels. */ + HILABEL = { ADDR adr; } 4 "<" adr. + LOLABEL = { ADDR adr; } 4 ">" adr. + +/* Primitives */ + + LABEL = { ADDR adr; } 4 adr. + CONST = { INT val; } 4 val. + LOCAL = { INT off; } 4. + +/* Allows us to use regvar() to refer to registers */ + + GPRE = { GPR reg; } 4 reg. + +/* Expression partial results */ + + SUM_RC = { GPR reg; INT off; } 4. + SUM_RR = { GPR reg1; GPR reg2; } 4. + + TRISTATE_RC_S = { GPR reg; INT val; } 4. + TRISTATE_RC_U = { GPR reg; INT val; } 4. + TRISTATE_RR_S = { GPR reg1; GPR reg2; } 4. + TRISTATE_RR_U = { GPR reg1; GPR reg2; } 4. + + TRISTATE_FF = { FPR reg1; FPR reg2; } 4. + + SEX_B = { GPR reg; } 4. + SEX_H = { GPR reg; } 4. + + IND_RC_B = { GPR reg; INT off; } 4. + IND_RC_H = { GPR reg; INT off; } 4. + IND_RC_H_S = { GPR reg; INT off; } 4. + IND_RC_W = { GPR reg; INT off; } 4. + IND_RR_W = { GPR reg1; GPR reg2; } 4. + IND_LABEL_W = { ADDR adr; } 4. + IND_RC_D = { GPR reg; INT off; } 8. + IND_RR_D = { GPR reg1; GPR reg2; } 8. + IND_LABEL_D = { ADDR adr; } 8. + + NOT_R = { GPR reg; } 4. + + AND_RR = { GPR reg1; GPR reg2; } 4. + AND_RC = { GPR reg; INT val; } 4. + OR_RR = { GPR reg1; GPR reg2; } 4. + OR_RC = { GPR reg; INT val; } 4. + XOR_RR = { GPR reg1; GPR reg2; } 4. + XOR_RC = { GPR reg; INT val; } 4. + +/* Floats */ + + FD = { FPR reg; } 8 reg. + FS = { FPR reg; } 4 reg. + +/* Comments */ + + LABELI = { ADDR msg; INT num; } 4 msg " " num. + + + + +SETS + + TOKEN = LABEL + CONST + LOCAL. + GPRI = GPR + GPRE. + + SUM_ALL = SUM_RC + SUM_RR. + + TRISTATE_ALL = TRISTATE_RC_S + TRISTATE_RC_U + TRISTATE_RR_S + + TRISTATE_RR_U + TRISTATE_FF. + + SEX_ALL = SEX_B + SEX_H. + + LOGICAL_ALL = NOT_R + AND_RR + AND_RC + OR_RR + OR_RC + XOR_RR + + XOR_RC. + + IND_ALL_W = IND_RC_W + IND_RR_W + IND_LABEL_W. + + IND_ALL_D = IND_RC_D + IND_RR_D + IND_LABEL_D. + + OP_ALL_W = SUM_ALL + TRISTATE_ALL + SEX_ALL + LOGICAL_ALL + + IND_ALL_W. + + +INSTRUCTIONS + + add GPRI:wo, GPRI:ro, GPRI:ro. + addX "add." GPRI:wo, GPRI:ro, GPRI:ro. + addi GPRI:wo, GPRI:ro, CONST:ro. + addis GPRI:wo, GPRI:ro, CONST+HILABEL:ro. + and GPRI:wo, GPRI:ro, GPRI:ro. + andc GPRI:wo, GPRI:ro, GPRI:ro. + andiX "andi." GPRI:wo, GPRI:ro, CONST:ro kills :cc. + andisX "andis." GPRI:wo, GPRI:ro, CONST:ro kills :cc. + b LABEL:ro. + bc CONST:ro, CONST:ro, LABEL:ro. + bcctr CONST:ro, CONST:ro, CONST:ro. + bcctrl CONST:ro, CONST:ro, CONST:ro. + bclr CONST:ro, CONST:ro, CONST:ro. + bl LABEL:ro. + cmp CR:ro, CONST:ro, GPRI:ro, GPR:ro kills :cc. + cmpi CR:ro, CONST:ro, GPRI:ro, CONST:ro kills :cc. + cmpl CR:ro, CONST:ro, GPRI:ro, GPR:ro kills :cc. + cmpli CR:ro, CONST:ro, GPRI:ro, CONST:ro kills :cc. + divw GPRI:wo, GPRI:ro, GPRI:ro. + divwu GPRI:wo, GPRI:ro, GPRI:ro. + eqv GPRI:wo, GPRI:ro, GPRI:ro. + extsb GPRI:wo, GPRI:ro. + extsh GPRI:wo, GPRI:ro. + fadd FD:wo, FD:ro, FD:ro. + fadds FS:wo, FS:ro, FS:ro. + fcmpo CR:wo, FD:ro, FD:ro. + fdiv FD:wo, FD:ro, FD:ro. + fdivs FS:wo, FS:ro, FS:ro. + fneg FS+FD:wo, FS+FD:ro. + fmul FD:wo, FD:ro, FD:ro. + fmuls FS:wo, FS:ro, FS:ro. + frsp FS:wo, FD:ro. + fsub FD:wo, FD:ro, FD:ro. + fsubs FS:wo, FS:ro, FS:ro. + fmr FS+FD:wo, FS+FD:ro. + lbzx GPRI:wo, GPR:ro, GPR:ro. + lbz GPRI:wo, GPRINDIRECT+GPRINDIRECTLO:ro. + lfd FD:wo, GPRINDIRECT+GPRINDIRECTLO:ro. + lfdu FD:wo, GPRINDIRECT+GPRINDIRECTLO:ro. + lfdx FD:wo, GPR:ro, GPR:ro. + lfs FS:wo, GPRINDIRECT+GPRINDIRECTLO:ro. + lfsu FS:wo, GPRINDIRECT+GPRINDIRECTLO:rw. + lfsx FS:wo, GPR:ro, GPR:ro. + lhzx GPRI:wo, GPR:ro, GPR:ro. + lhax GPRI:wo, GPR:ro, GPR:ro. + lha GPRI:wo, GPRINDIRECT+GPRINDIRECTLO:ro. + lhz GPRI:wo, GPRINDIRECT+GPRINDIRECTLO:ro. + lwzu GPRI:wo, GPRINDIRECT+GPRINDIRECTLO:ro. + lwzx GPRI:wo, GPR:ro, GPR:ro. + lwz GPRI:wo, GPRINDIRECT+GPRINDIRECTLO:ro. + nand GPRI:wo, GPRI:ro, GPRI:ro. + neg GPRI:wo, GPRI:ro. + nor GPRI:wo, GPRI:ro, GPRI:ro. + mfcr GPRI:wo. + mullw GPRI:wo, GPRI:ro, GPRI:ro. + mfspr GPRI:wo, SPR:ro. + mtspr SPR:wo, GPRI:ro. + or GPRI:wo, GPRI:ro, GPRI:ro. + orc GPRI:wo, GPRI:ro, GPRI:ro. + ori GPRI:wo, GPRI:ro, CONST+LOLABEL:ro. + orX "or." GPRI:wo, GPRI:ro, GPRI:ro kills :cc. + rlwinm GPRI:wo, GPRI:ro, CONST:ro, CONST:ro, CONST:ro. + slw GPRI:wo, GPRI:ro, GPRI:ro. + subf GPRI:wo, GPRI:ro, GPRI:ro. + sraw GPRI:wo, GPRI:ro, GPRI:ro. + srawi GPRI:wo, GPRI:ro, CONST:ro. + srw GPRI:wo, GPRI:ro, GPRI:ro. + stb GPRI:ro, GPRINDIRECT+GPRINDIRECTLO:rw. + stbx GPRI:ro, GPR:ro, GPR:ro. + stfd FD:ro, GPRINDIRECT+GPRINDIRECTLO:rw. + stfdu FD:ro, GPRINDIRECT+GPRINDIRECTLO:rw. + stfdx FD:ro, GPR:ro, GPR:ro. + stfs FS:ro, GPRINDIRECT+GPRINDIRECTLO:rw. + stfsu FS:ro, GPRINDIRECT+GPRINDIRECTLO:rw. + stfsx FS:ro, GPR:ro, GPR:ro. + sth GPRI:ro, GPRINDIRECT+GPRINDIRECTLO:rw. + sthx GPRI:ro, GPR:ro, GPR:ro. + stw GPRI:ro, GPRINDIRECT+GPRINDIRECTLO:rw. + stwx GPRI:ro, GPR:ro, GPR:ro. + stwu GPRI:ro, GPRINDIRECT+GPRINDIRECTLO:rw. + xor GPRI:wo, GPRI:ro, GPRI:ro. + xori GPRI:wo, GPRI:ro, CONST:ro. + + gpr_gpr_gpr GPRI:wo, GPRI:ro, GPRI:ro. + gpr_gpr_si GPRI:wo, GPRI:ro, CONST:ro. + gpr_ro_gprindirect GPRI:ro, GPRINDIRECT:rw. + gpr_ro_gpr_gpr GPRI:ro, GPRI:ro, GPRI:ro. + gpr_wo_gprindirect GPRI:wo, GPRINDIRECT:ro. + gpr_wo_gpr_gpr GPRI:wo, GPRI:ro, GPRI:ro. + + invalid "invalid". + comment "!" LABEL+LABELI:ro. + + + +MOVES + + from GPR to GPR + gen + COMMENT("move GPR->GPR") + or %2, %1, %1 + +/* GPRE exists solely to allow us to use regvar() (which can only be used in + an expression) as a register constant. */ + + from GPR to GPRE + gen + COMMENT("move GPR->GPRE") + or %2, %1, %1 + +/* Constants */ + + from CONST smalls(%val) to GPR + gen + COMMENT("move CONST->GPRE") + addi %2, R0, {CONST, lo(%1.val)} + + from CONST to GPR + gen + COMMENT("move CONST->GPRE") + addis %2, R0, {CONST, hi(%1.val)} + ori %2, %2, {CONST, lo(%1.val)} + + from LABEL to GPR + gen + COMMENT("move LABEL->GPR") + addis %2, R0, {HILABEL, %1.adr} + ori %2, %2, {LOLABEL, %1.adr} + +/* Sign extension */ + + from SEX_B to GPR + gen + COMMENT("move SEX_B->GPR") + extsb %2, %1.reg + + from SEX_H to GPR + gen + COMMENT("move SEX_H->GPR") + extsh %2, %1.reg + +/* Register + something */ + + from SUM_RC smalls(%off) to GPR + gen + COMMENT("move SUM_RC->GPR smalls") + addi %2, %1.reg, {CONST, lo(%1.off)} + + from SUM_RC to GPR + gen + COMMENT("move SUM_RC->GPR large") + addi %2, %1.reg, {CONST, los(%1.off)} + addis %2, %2, {CONST, his(%1.off)} + + from SUM_RR to GPR + gen + COMMENT("move SUM_RR->GPR") + add %2, %1.reg1, %1.reg2 + + from SUM_RR to GPR + gen + COMMENT("move SUM_RR->GPRE") + add %2, %1.reg1, %1.reg2 + +/* Read/write byte */ + + from IND_RC_B smalls(%off) to GPR + gen + COMMENT("move IND_RC_B->GPR small") + lbz %2, {GPRINDIRECT, %1.reg, %1.off} + + from IND_RC_B to GPR + gen + COMMENT("move IND_RC_B->GPR large") + addis SCRATCH, %1.reg, {CONST, his(%1.off)} + lbz %2, {GPRINDIRECT, SCRATCH, los(%1.off)} + + from GPR to IND_RC_B smalls(%off) + gen + COMMENT("move GPR->IND_RC_B small") + stb %1, {GPRINDIRECT, %2.reg, %2.off} + + from GPR to IND_RC_B + gen + COMMENT("move GPR->IND_RC_B large") + addis SCRATCH, %2.reg, {CONST, his(%2.off)} + stb %1, {GPRINDIRECT, SCRATCH, los(%2.off)} + +/* Read/write short */ + + from IND_RC_H smalls(%off) to GPR + gen + COMMENT("move IND_RC_H->GPR small") + lhz %2, {GPRINDIRECT, %1.reg, %1.off} + + from IND_RC_H to GPR + gen + COMMENT("move IND_RC_H->GPR large") + addis SCRATCH, %1.reg, {CONST, his(%1.off)} + lhz %2, {GPRINDIRECT, SCRATCH, los(%1.off)} + + from IND_RC_H_S smalls(%off) to GPR + gen + COMMENT("move IND_RC_H_S->GPR small") + lha %2, {GPRINDIRECT, %1.reg, %1.off} + + from IND_RC_H_S to GPR + gen + COMMENT("move IND_RC_H_S->GPR large") + addis SCRATCH, %1.reg, {CONST, his(%1.off)} + lha %2, {GPRINDIRECT, SCRATCH, los(%1.off)} + + from GPR to IND_RC_H smalls(%off) + gen + COMMENT("move GPR->IND_RC_H small") + sth %1, {GPRINDIRECT, %2.reg, %2.off} + + from GPR to IND_RC_H + gen + COMMENT("move GPR->IND_RC_H large") + addis SCRATCH, %2.reg, {CONST, his(%2.off)} + sth %1, {GPRINDIRECT, SCRATCH, los(%2.off)} + +/* Read word */ + + from IND_RC_W smalls(%off) to GPR + gen + COMMENT("move IND_RC_W->GPR small") + lwz %2, {GPRINDIRECT, %1.reg, %1.off} + + from IND_RC_W to GPR + gen + COMMENT("move IND_RC_W->GPR large") + addis %2, %1.reg, {CONST, his(%1.off)} + lwz %2, {GPRINDIRECT, %2, los(%1.off)} + + from IND_RR_W to GPR + gen + COMMENT("move IND_RR_W->GPR") + lwzx %2, %1.reg1, %1.reg2 + + from IND_LABEL_W to GPR + gen + COMMENT("move IND_LABEL_W->GPR") + move {LABEL, %1.adr}, SCRATCH + lwz %2, {GPRINDIRECT, SCRATCH, 0} + + from IND_RC_W smalls(%off) to FS + gen + COMMENT("move IND_RC_W->FS small") + lfs %2, {GPRINDIRECT, %1.reg, %1.off} + + from IND_RC_W to FS + gen + COMMENT("move IND_RC_W->FS large") + addis SCRATCH, %1.reg, {CONST, his(%1.off)} + lfs %2, {GPRINDIRECT, SCRATCH, los(%1.off)} + + from IND_RR_W to FS + gen + COMMENT("move IND_RR_W->FS") + lfsx %2, %1.reg1, %1.reg2 + + from IND_LABEL_W to FS + gen + COMMENT("move IND_LABEL_W->FS") + move {LABEL, %1.adr}, SCRATCH + lfs %2, {GPRINDIRECT, SCRATCH, 0} + +/* Write word */ + + from GPR to IND_RC_W smalls(%off) + gen + COMMENT("move GPR->IND_RC_W small") + stw %1, {GPRINDIRECT, %2.reg, %2.off} + + from GPR to IND_RC_W + gen + COMMENT("move GPR->IND_RC_W large") + addis SCRATCH, %2.reg, {CONST, his(%2.off)} + stw %1, {GPRINDIRECT, SCRATCH, los(%2.off)} + + from GPR to IND_RR_W + gen + COMMENT("move GPR->IND_RR_W") + stwx %1, %2.reg1, %2.reg2 + + from GPR to IND_LABEL_W + gen + COMMENT("move GPR->IND_LABEL_D") + move {LABEL, %2.adr}, SCRATCH + stw %1, {GPRINDIRECT, SCRATCH, 0} + + from FS to IND_RC_W smalls(%off) + gen + COMMENT("move FS->IND_RC_W small") + stfs %1, {GPRINDIRECT, %2.reg, %2.off} + + from FS to IND_RC_W + gen + COMMENT("move FS->IND_RC_W large") + addis SCRATCH, %2.reg, {CONST, his(%2.off)} + stfs %1, {GPRINDIRECT, SCRATCH, los(%2.off)} + + from FS to IND_RR_W + gen + COMMENT("move FS->IND_RR_W") + stfsx %1, %2.reg1, %2.reg2 + + from FS to IND_LABEL_W + gen + COMMENT("move FS->IND_LABEL_D") + move {LABEL, %2.adr}, SCRATCH + stfs %1, {GPRINDIRECT, SCRATCH, 0} + +/* Read double */ + + from IND_RC_D smalls(%off) to FD + gen + COMMENT("move IND_RC_D->FD small") + lfd %2, {GPRINDIRECT, %1.reg, %1.off} + + from IND_RC_D to FD + gen + COMMENT("move IND_RC_D->FD large") + addis SCRATCH, %1.reg, {CONST, his(%1.off)} + lfd %2, {GPRINDIRECT, SCRATCH, los(%1.off)} + + from IND_RR_D to FD + gen + COMMENT("move IND_RR_D->FD") + lfdx %2, %1.reg1, %1.reg2 + + from IND_LABEL_D to FD + gen + COMMENT("move IND_LABEL_D->FD") + move {LABEL, %1.adr}, SCRATCH + lfd %2, {GPRINDIRECT, SCRATCH, 0} + +/* Write double */ + + from FD to IND_RC_D smalls(%off) + gen + COMMENT("move FD->IND_RC_D small") + stfd %1, {GPRINDIRECT, %2.reg, %2.off} + + from FD to IND_RC_D + gen + COMMENT("move FD->IND_RC_D large") + addis SCRATCH, %2.reg, {CONST, his(%2.off)} + stfd %1, {GPRINDIRECT, SCRATCH, los(%2.off)} + + from FD to IND_RR_D + gen + COMMENT("move FD->IND_RR_W") + stfdx %1, %2.reg1, %2.reg2 + + from FD to IND_LABEL_D + gen + COMMENT("move FD->IND_LABEL_D") + move {LABEL, %2.adr}, SCRATCH + stfd %1, {GPRINDIRECT, SCRATCH, 0} + +/* Extract condition code field (actually produces (CC&3)<<2) */ + + from CR0 to GPR + gen + COMMENT("move CR0->GPR") + mfcr %2 + rlwinm %2, %2, {CONST, 4}, {CONST, 32-4}, {CONST, 31-2} + +/* Comparisons */ + + from TRISTATE_RR_S to CR0 + gen + cmp %2, {CONST, 0}, %1.reg1, %1.reg2 + + from TRISTATE_RR_U to CR0 + gen + cmpl %2, {CONST, 0}, %1.reg1, %1.reg2 + + from TRISTATE_RC_S to CR0 + gen + COMMENT("move TRISTATE_RC_S->CR0 large") + move {CONST, %1.val}, SCRATCH + cmp %2, {CONST, 0}, %1.reg, SCRATCH + + from TRISTATE_RC_U smallu(%val) to CR0 + gen + COMMENT("move TRISTATE_RC_U->CR0 small") + cmpli %2, {CONST, 0}, %1.reg, {CONST, %1.val} + + from TRISTATE_RC_U to CR0 + gen + COMMENT("move TRISTATE_RC_U->CR0") + move {CONST, %1.val}, SCRATCH + cmpl %2, {CONST, 0}, %1.reg, SCRATCH + + from TRISTATE_FF to CR0 + gen + COMMENT("move TRISTATE_FF->CR0") + fcmpo %2, {FD, %1.reg1}, {FD, %1.reg2} + + from GPR to CR0 + gen + COMMENT("move GPR->CR0") + orX SCRATCH, %1, %1 /* alas, can't call test */ + + from TRISTATE_RR_S + TRISTATE_RC_S + TRISTATE_FF to GPR + gen + COMMENT("move TRISTATE_R*_S->GPR") + move %1, C0 + move C0, SCRATCH + move {LABEL, ".tristate_s_table"}, %2 + lwzx %2, %2, SCRATCH + + from TRISTATE_RR_U + TRISTATE_RC_U to GPR + gen + COMMENT("move TRISTATE_R*_U->GPR") + move %1, C0 + move C0, SCRATCH + move {LABEL, ".tristate_u_table"}, %2 + lwzx %2, %2, SCRATCH + +/* Logicals */ + + from NOT_R to GPR + gen + COMMENT("move NOT_R->GPR") + nor %2, %1.reg, %1.reg + + from AND_RR to GPR + gen + COMMENT("move AND_RR->GPR") + and %2, %1.reg1, %1.reg2 + + from AND_RC smallu(%val) to GPR + gen + COMMENT("move AND_RC->GPR small") + andiX %2, %1.reg, {CONST, %1.val} + + from AND_RC to GPR + gen + COMMENT("move AND_RC->GPR") + move {CONST, %1.val}, SCRATCH + and %2, %1.reg, SCRATCH + + from OR_RR to GPR + gen + COMMENT("move OR_RR->GPR") + or %2, %1.reg1, %1.reg2 + + from OR_RC smallu(%val) to GPR + gen + COMMENT("move OR_RC->GPR small") + ori %2, %1.reg, {CONST, %1.val} + + from OR_RC to GPR + gen + COMMENT("move OR_RC->GPR") + move {CONST, %1.val}, SCRATCH + or %2, %1.reg, SCRATCH + + from XOR_RR to GPR + gen + COMMENT("move XOR_RR->GPR") + xor %2, %1.reg1, %1.reg2 + + from XOR_RC smallu(%val) to GPR + gen + COMMENT("move XOR_RC->GPR small") + xori %2, %1.reg, {CONST, %1.val} + + from XOR_RC to GPR + gen + COMMENT("move XOR_RC->GPR") + move {CONST, %1.val}, SCRATCH + xor %2, %1.reg, SCRATCH + +/* Miscellaneous */ + + from OP_ALL_W + LABEL + CONST to GPRE + gen + move %1, %2.reg + + +TESTS + + to test GPR + gen + orX SCRATCH, %1, %1 + + + +STACKINGRULES + + from GPR to STACK + gen + COMMENT("stack GPR") + stwu %1, {GPRINDIRECT, SP, 0-4} + + from CONST to STACK + uses REG + gen + COMMENT("stack CONST") + move %1, %a + stwu %a, {GPRINDIRECT, SP, 0-4} + + from LABEL to STACK + uses REG + gen + COMMENT("stack LABEL") + move %1, {GPRE, %a} + stwu %a, {GPRINDIRECT, SP, 0-4} + + from SEX_B to STACK + gen + COMMENT("stack SEX_B") + extsb SCRATCH, %1.reg + stwu SCRATCH, {GPRINDIRECT, SP, 0-4} + + from SEX_H to STACK + gen + COMMENT("stack SEX_H") + extsh SCRATCH, %1.reg + stwu SCRATCH, {GPRINDIRECT, SP, 0-4} + + from SUM_ALL + TRISTATE_ALL + LOGICAL_ALL to STACK + gen + move %1, {GPRE, SCRATCH} + stwu SCRATCH, {GPRINDIRECT, SP, 0-4} + + from IND_ALL_W to STACK + gen + move %1, SCRATCH + stwu SCRATCH, {GPRINDIRECT, SP, 0-4} + + from IND_ALL_D to STACK + gen + move %1, {FD, FSCRATCH} + stfdu {FD, FSCRATCH}, {GPRINDIRECT, SP, 0-8} + + from FD to STACK + gen + COMMENT("stack FD") + stfdu %1, {GPRINDIRECT, SP, 0-8} + + from FS to STACK + gen + COMMENT("stack FS") + stfsu %1, {GPRINDIRECT, SP, 0-4} + + from TOKEN to STACK + gen + invalid. + + + +COERCIONS + + from REG + uses REG + gen + COMMENT("coerce REG->REG") + move %1, %a + yields %a + + from CONST + uses REG + gen + COMMENT("coerce CONST->REG") + move %1, %a + yields %a + + from LABEL + uses REG + gen + COMMENT("coerce LABEL->REG") + move %1, {GPRE, %a} + yields %a + + from STACK + uses REG + gen + COMMENT("coerce STACK->REG") + lwz %a, {GPRINDIRECT, SP, 0} + addi SP, SP, {CONST, 4} + yields %a + + from SEX_B + uses REG + gen + COMMENT("coerce SEX_B->REG") + extsb %a, %1.reg + yields %a + + from SEX_H + uses REG + gen + COMMENT("coerce SEX_H->REG") + extsh %a, %1.reg + yields %a + + from SUM_ALL + TRISTATE_ALL + LOGICAL_ALL + uses REG + gen + move %1, {GPRE, %a} + yields %a + + from FS + uses FREG + gen + fmr {FS, %a}, %1 + yields {FS, %a} + + from FD + uses FREG + gen + fmr {FD, %a}, %1 + yields {FD, %a} + + from STACK + uses FREG + gen + COMMENT("coerce STACK->FD") + lfd {FD, %a}, {GPRINDIRECT, SP, 0} + addi SP, SP, {CONST, 8} + yields {FD, %a} + + from STACK + uses FREG + gen + COMMENT("coerce STACK->FS") + lfs {FS, %a}, {GPRINDIRECT, SP, 0} + addi SP, SP, {CONST, 4} + yields {FS, %a} + + from IND_ALL_W + uses REG + gen + move %1, %a + yields %a + + from IND_ALL_W + uses FREG + gen + move %1, {FS, %a} + yields {FS, %a} + + from IND_ALL_D + uses FREG + gen + move %1, {FD, %a} + yields {FD, %a} + + + + +PATTERNS + +/* Intrinsics */ + + pat loc /* Load constant */ + yields {CONST, $1} + + pat dup $1==INT32 /* Duplicate word on top of stack */ + with GPR + yields %1 %1 + + pat dup $1==INT64 /* Duplicate double-word on top of stack */ + with GPR GPR + yields %2 %1 %2 %1 + + pat exg $1==INT32 /* Exchange top two words on stack */ + with GPR GPR + yields %1 %2 + + pat stl lol $1==$2 /* Store then load local */ + leaving + dup 4 + stl $1 + + pat lal sti lal loi $1==$3 && $2==$4 /* Store then load local, of a different size */ + leaving + dup INT32 + lal $1 + sti $2 + + pat ste loe $1==$2 /* Store then load external */ + leaving + dup 4 + ste $1 + + +/* Type conversions */ + + pat loc loc cii loc loc cii $1==$4 && $2==$5 /* madness, generated by the C compiler */ + leaving + loc $1 + loc $2 + cii + + pat loc loc cii loc loc cii $2==INT32 && $5==INT32 && $4<$2 /* madness, generated by the C compiler */ + leaving + loc $4 + loc $5 + cii + + pat loc loc ciu /* signed X -> unsigned X */ + leaving + loc $1 + loc $2 + cuu + + pat loc loc cuu $1==$2 /* unsigned X -> unsigned X */ + /* nop */ + + pat loc loc cii $1==$2 /* signed X -> signed X */ + /* nop */ + + pat loc loc cui $1==$2 /* unsigned X -> signed X */ + /* nop */ + + pat loc loc cui $1==INT8 && $2==INT32 /* unsigned char -> signed int */ + /* nop */ + + pat loc loc cui $1==INT16 && $2==INT32 /* unsigned short -> signed int */ + /* nop */ + + pat loc loc cii $1==INT8 && $2==INT32 /* signed char -> signed int */ + with GPR + yields {SEX_B, %1} + + pat loc loc cii $1==2 && $2==4 /* signed char -> signed short */ + with GPR + yields {SEX_H, %1} + + + + + +/* Local variables */ + + pat lal /* Load address of local */ + yields {SUM_RC, FP, $1} + + pat lol inreg($1)>0 /* Load from local */ + yields {LOCAL, $1} + + pat lol /* Load from local */ + leaving + lal $1 + loi INT32 + + pat ldl /* Load double-word from local */ + leaving + lal $1 + loi INT32*2 + + pat stl inreg($1)>0 /* Store to local */ + with CONST + LABEL + GPR + OP_ALL_W + kills regvar($1), LOCAL %off==$1 + gen + move %1, {GPRE, regvar($1)} + + pat stl /* Store to local */ + leaving + lal $1 + sti INT32 + + pat sdl /* Store double-word to local */ + leaving + lal $1 + sti INT32*2 + + pat lil inreg($1)>0 /* Load from indirected local */ + uses REG + gen + lwz %a, {GPRINDIRECT, regvar($1), 0} + yields %a + + pat lil /* Load from indirected local */ + leaving + lol $1 + loi INT32 + + pat sil /* Save to indirected local */ + leaving + lol $1 + sti INT32 + + pat stl lol $1==$2 /* Save then load (generated by C compiler) */ + leaving + dup 4 + stl $1 + + pat zrl /* Zero local */ + leaving + loc 0 + stl $1 + + pat inl /* Increment local */ + leaving + lol $1 + loc 1 + adi 4 + stl $1 + + pat del /* Decrement local */ + leaving + lol $1 + loc 1 + sbi 4 + stl $1 + + +/* Global variables */ + + pat lpi /* Load address of external function */ + leaving + lae $1 + + pat lae /* Load address of external */ + yields {LABEL, $1} + + pat loe /* Load word external */ + leaving + lae $1 + loi INT32 + + pat ste /* Store word external */ + leaving + lae $1 + sti INT32 + + pat lde /* Load double-word external */ + leaving + lae $1 + loi INT64 + + pat sde /* Store double-word external */ + leaving + lae $1 + sti INT64 + + pat zre /* Zero external */ + leaving + loc 0 + ste $1 + + pat ine /* Increment external */ + uses REG={LABEL, $1}, REG + gen + lwz %b, {GPRINDIRECT, %a, 0} + addi %b, %b, {CONST, 1} + stw %b, {GPRINDIRECT, %a, 0} + + pat dee /* Decrement external */ + uses REG={LABEL, $1}, REG + gen + lwz %b, {GPRINDIRECT, %a, 0} + addi %b, %b, {CONST, 0-1} + stw %b, {GPRINDIRECT, %a, 0} + + + +/* Structures */ + + pat lof /* Load word offsetted */ + leaving + adp $1 + loi INT32 + + pat ldf /* Load double-word offsetted */ + leaving + adp $1 + loi INT64 + + pat stf /* Store word offsetted */ + leaving + adp $1 + sti INT32 + + pat sdf /* Store double-word offsetted */ + leaving + adp $1 + sti INT64 + + + +/* Loads and stores */ + + pat loi $1==INT8 /* Load byte indirect */ + with GPR + uses REG + gen + lbz %a, {GPRINDIRECT, %1, 0} + yields %a + with SUM_RR + uses reusing %1, REG + gen + lbzx %a, %1.reg1, %1.reg2 + yields %a + with SUM_RC + uses REG + gen + move {IND_RC_B, %1.reg, %1.off}, %a + yields %a + + pat loi loc loc cii $1==INT16 && $2==INT16 && $3==INT32 /* Load half-word indirect and sign extend */ + with GPR + uses REG + gen + lha %a, {GPRINDIRECT, %1, 0} + yields %a + with SUM_RR + uses reusing %1, REG + gen + lhax %a, %1.reg1, %1.reg2 + yields %a + with SUM_RC + uses REG + gen + move {IND_RC_H_S, %1.reg, %1.off}, %a + yields %a + + pat loi $1==INT16 /* Load half-word indirect */ + with GPR + uses REG + gen + lhz %a, {GPRINDIRECT, %1, 0} + yields %a + with SUM_RR + uses reusing %1, REG + gen + lhzx %a, %1.reg1, %1.reg2 + yields %a + with SUM_RC + uses REG + gen + move {IND_RC_H, %1.reg, %1.off}, %a + yields %a + + pat loi $1==INT32 /* Load word indirect */ + with GPR + yields {IND_RC_W, %1, 0} + with SUM_RC + yields {IND_RC_W, %1.reg, %1.off} + with SUM_RR + yields {IND_RR_W, %1.reg1, %1.reg2} + with LABEL + yields {IND_LABEL_W, %1.adr} + + pat loi $1==INT64 /* Load double-word indirect */ + with GPR + yields {IND_RC_D, %1, 0} + with SUM_RC + yields {IND_RC_D, %1.reg, %1.off} + with SUM_RR + yields {IND_RR_D, %1.reg1, %1.reg2} + with LABEL + yields {IND_LABEL_D, %1.adr} + + pat loi /* Load arbitrary size */ + leaving + loc $1 + los INT32 + + pat los /* Load arbitrary size */ + with GPR3 GPR4 STACK + kills ALL + gen + bl {LABEL, ".los"} + + pat sti $1==INT8 /* Store byte indirect */ + with GPR GPR + gen + stb %2, {GPRINDIRECT, %1, 0} + with SUM_RR GPR + gen + stbx %2, %1.reg1, %1.reg2 + with SUM_RC GPR + gen + move %2, {IND_RC_B, %1.reg, %1.off} + with GPR SEX_B + gen + stb %2.reg, {GPRINDIRECT, %1, 0} + with SUM_RR SEX_B + gen + stbx %2.reg, %1.reg1, %1.reg2 + with SUM_RC SEX_B + gen + move %2.reg, {IND_RC_B, %1.reg, %1.off} + + pat sti $1==INT16 /* Store half-word indirect */ + with GPR GPR + gen + sth %2, {GPRINDIRECT, %1, 0} + with SUM_RR GPR + gen + sthx %2, %1.reg1, %1.reg2 + with SUM_RC GPR + gen + move %2, {IND_RC_H, %1.reg, %1.off} + with GPR SEX_H + gen + sth %2.reg, {GPRINDIRECT, %1, 0} + with SUM_RR SEX_H + gen + sthx %2.reg, %1.reg1, %1.reg2 + with SUM_RC SEX_H + gen + move %2.reg, {IND_RC_H, %1.reg, %1.off} + + pat sti $1==INT32 /* Store word indirect */ + with GPR GPR+FS + gen + move %2, {IND_RC_W, %1, 0} + with SUM_RR GPR+FS + gen + move %2, {IND_RR_W, %1.reg1, %1.reg2} + with SUM_RC GPR+FS + gen + move %2, {IND_RC_W, %1.reg, %1.off} + with LABEL GPR+FS + gen + move %2, {IND_LABEL_W, %1.adr} + + pat sti $1==INT64 /* Store double-word indirect */ + with GPR FD + gen + move %2, {IND_RC_D, %1, 0} + with SUM_RR FD + gen + move %2, {IND_RR_D, %1.reg1, %1.reg2} + with SUM_RC FD + gen + move %2, {IND_RC_D, %1.reg, %1.off} + with GPR GPR GPR + gen + stw %2, {GPRINDIRECT, %1, 0} + stw %3, {GPRINDIRECT, %1, 4} + with SUM_RC GPR GPR + gen + move %2, {IND_RC_W, %1.reg, %1.off} + move %3, {IND_RC_W, %1.reg, %1.off+4} + with LABEL FD + gen + move %2, {IND_LABEL_D, %1.adr} + + + pat sti /* Store arbitrary size */ + leaving + loc $1 + sts INT32 + + pat sts /* Load arbitrary size */ + with GPR3 GPR4 STACK + kills ALL + gen + bl {LABEL, ".sts"} + + + +/* Arithmetic wrappers */ + + pat ads $1==4 /* Add var to pointer */ + leaving adi $1 + + pat sbs $1==4 /* Subtract var from pointer */ + leaving sbi $1 + + pat adp /* Add constant to pointer */ + leaving + loc $1 + adi 4 + + pat adu /* Add unsigned */ + leaving + adi $1 + + pat sbu /* Subtract unsigned */ + leaving + sbi $1 + + pat inc /* Add 1 */ + leaving + loc 1 + adi 4 + + pat dec /* Subtract 1 */ + leaving + loc 1 + sbi 4 + + pat loc mlu $2==2 /* Unsigned multiply by constant */ + leaving + loc $1 + mli 4 + + pat mlu /* Unsigned multiply by var */ + leaving + mli $1 + + pat loc slu /* Shift left unsigned by constant amount */ + leaving + loc $1 + sli $2 + + pat slu /* Shift left unsigned by variable amount */ + leaving + sli $1 + + + +/* Word arithmetic */ + + pat adi $1==4 /* Add word (second + top) */ + with REG REG + yields {SUM_RR, %1, %2} + with CONST REG + yields {SUM_RC, %2, %1.val} + with REG CONST + yields {SUM_RC, %1, %2.val} + with CONST SUM_RC + yields {SUM_RC, %2.reg, %2.off+%1.val} + with CONST LABEL + yields {LABEL, %2.adr+%1.val} + + pat sbi $1==4 /* Subtract word (second - top) */ + with REG REG + uses reusing %2, REG + gen + subf %a, %1, %2 + yields %a + with CONST REG + yields {SUM_RC, %2, 0-%1.val} + with CONST SUM_RC + yields {SUM_RC, %2.reg, %2.off-%1.val} + with CONST LABEL + yields {LABEL, %2.adr+(0-%1.val)} + + pat ngi $1==4 /* Negate word */ + with REG + uses reusing %1, REG + gen + neg %a, %1 + yields %a + + pat mli $1==4 /* Multiply word (second * top) */ + with REG REG + uses reusing %2, REG + gen + mullw %a, %2, %1 + yields %a + + pat dvi $1==4 /* Divide word (second / top) */ + with REG REG + uses reusing %2, REG + gen + divw %a, %2, %1 + yields %a + + pat dvu $1==4 /* Divide unsigned word (second / top) */ + with REG REG + uses reusing %2, REG + gen + divwu %a, %2, %1 + yields %a + + pat rmi $1==4 /* Remainder word (second % top) */ + with REG REG + uses REG + gen + divw %a, %2, %1 + mullw %a, %a, %1 + subf %a, %a, %2 + yields %a + + pat rmu $1==4 /* Remainder unsigned word (second % top) */ + with REG REG + uses REG + gen + divwu %a, %2, %1 + mullw %a, %a, %1 + subf %a, %a, %2 + yields %a + + pat and $1==4 /* AND word */ + with GPR NOT_R + uses reusing %1, REG + gen + andc %a, %1, %2.reg + yields %a + with NOT_R GPR + uses reusing %1, REG + gen + andc %a, %2, %1.reg + yields %a + with GPR GPR + yields {AND_RR, %1, %2} + with GPR CONST + yields {AND_RC, %1, %2.val} + with CONST GPR + yields {AND_RC, %2, %1.val} + + pat and !defined($1) /* AND set */ + with STACK + gen + bl {LABEL, ".and"} + + pat ior $1==4 /* OR word */ + with GPR NOT_R + uses reusing %1, REG + gen + orc %a, %1, %2.reg + yields %a + with NOT_R GPR + uses reusing %2, REG + gen + orc %a, %2, %1.reg + yields %a + with GPR GPR + yields {OR_RR, %1, %2} + with GPR CONST + yields {OR_RC, %1, %2.val} + with CONST GPR + yields {OR_RC, %2, %1.val} + + pat ior !defined($1) /* OR set */ + with STACK + gen + bl {LABEL, ".ior"} + + pat xor $1==4 /* XOR word */ + with GPR GPR + yields {XOR_RR, %1, %2} + with GPR CONST + yields {XOR_RC, %1, %2.val} + with CONST GPR + yields {XOR_RC, %2, %1.val} + + pat xor !defined($1) /* XOR set */ + with STACK + gen + bl {LABEL, ".xor"} + + pat com $1==INT32 /* NOT word */ + with AND_RR + uses REG + gen + nand %a, %1.reg1, %1.reg2 + yields %a + with OR_RR + uses REG + gen + nor %a, %1.reg1, %1.reg2 + yields %a + with XOR_RR + uses REG + gen + eqv %a, %1.reg1, %1.reg2 + yields %a + with GPR + yields {NOT_R, %1} + + pat com !defined($1) /* NOT set */ + with STACK + gen + bl {LABEL, ".com"} + + pat sli $1==4 /* Shift left (second << top) */ + with CONST GPR + uses reusing %2, REG + gen + rlwinm %a, %2, {CONST, (%1.val & 0x1F)}, {CONST, 0}, {CONST, 31-(%1.val & 0x1F)} + yields %a + with GPR GPR + uses reusing %2, REG + gen + slw %a, %2, %1 + yields %a + + pat sri $1==4 /* Shift right signed (second >> top) */ + with CONST GPR + uses reusing %2, REG + gen + srawi %a, %2, {CONST, %1.val & 0x1F} + yields %a + with GPR GPR + uses reusing %2, REG + gen + sraw %a, %2, %1 + yields %a + + pat sru $1==4 /* Shift right unsigned (second >> top) */ + with CONST GPR + uses reusing %2, REG + gen + rlwinm %a, %2, {CONST, 32-(%1.val & 0x1F)}, {CONST, (%1.val & 0x1F)}, {CONST, 31} + yields %a + with GPR GPR + uses reusing %2, REG + gen + srw %a, %2, %1 + yields %a + + + +/* Arrays */ + + pat aar $1==INT32 /* Index array */ + with GPR3 GPR4 GPR5 + gen + bl {LABEL, ".aar4"} + yields R3 + + pat lae lar $2==INT32 && nicesize(rom($1, 3)) /* Load array */ + leaving + lae $1 + aar INT32 + loi rom($1, 3) + + pat lar $1==INT32 /* Load array */ + with GPR3 GPR4 GPR5 STACK + kills ALL + gen + bl {LABEL, ".lar4"} + + pat lae sar $2==INT32 && nicesize(rom($1, 3)) /* Store array */ + leaving + lae $1 + aar INT32 + sti rom($1, 3) + + pat sar $1==INT32 /* Store array */ + with GPR3 GPR4 GPR5 STACK + kills ALL + gen + bl {LABEL, ".sar4"} + + + + +/* Sets */ + + pat set defined($1) /* Create word with set bit */ + leaving + loc 1 + exg INT32 + sli INT32 + + pat set !defined($1) /* Create structure with set bit (variable) */ + with GPR3 GPR4 STACK + gen + bl {LABEL, ".set"} + + pat inn defined($1) /* Test for set bit */ + leaving + set INT32 + and INT32 + + pat inn !defined($1) /* Test for set bit (variable) */ + with GPR3 STACK + gen + bl {LABEL, ".inn"} + + + +/* Boolean resolutions */ + + pat teq /* top = (top == 0) */ + with TRISTATE_ALL + GPR + uses reusing %1, REG + gen + move %1, C0 + move C0, SCRATCH + move {LABEL, ".teq_table"}, %a + lwzx %a, %a, SCRATCH + yields %a + + pat tne /* top = (top != 0) */ + with TRISTATE_ALL + GPR + uses reusing %1, REG + gen + move %1, C0 + move C0, SCRATCH + move {LABEL, ".tne_table"}, %a + lwzx %a, %a, SCRATCH + yields %a + + pat tlt /* top = (top < 0) */ + with TRISTATE_ALL + GPR + uses reusing %1, REG + gen + move %1, C0 + move C0, SCRATCH + move {LABEL, ".tlt_table"}, %a + lwzx %a, %a, SCRATCH + yields %a + + pat tle /* top = (top <= 0) */ + with TRISTATE_ALL + GPR + uses reusing %1, REG + gen + move %1, C0 + move C0, SCRATCH + move {LABEL, ".tle_table"}, %a + lwzx %a, %a, SCRATCH + yields %a + + pat tgt /* top = (top > 0) */ + with TRISTATE_ALL + GPR + uses reusing %1, REG + gen + move %1, C0 + move C0, SCRATCH + move {LABEL, ".tgt_table"}, %a + lwzx %a, %a, SCRATCH + yields %a + + pat tge /* top = (top >= 0) */ + with TRISTATE_ALL + GPR + uses reusing %1, REG + gen + move %1, C0 + move C0, SCRATCH + move {LABEL, ".tge_table"}, %a + lwzx %a, %a, SCRATCH + yields %a + + + + +/* Simple branches */ + + pat zeq /* Branch if signed top == 0 */ + with TRISTATE_ALL+GPR STACK + gen + move %1, C0 + bc IFTRUE, EQ, {LABEL, $1} + + pat beq + leaving + cmi INT32 + zeq $1 + + pat zne /* Branch if signed top != 0 */ + with TRISTATE_ALL+GPR STACK + gen + move %1, C0 + bc IFFALSE, EQ, {LABEL, $1} + + pat bne + leaving + cmi INT32 + zne $1 + + pat zgt /* Branch if signed top > 0 */ + with TRISTATE_ALL+GPR STACK + gen + move %1, C0 + bc IFTRUE, GT, {LABEL, $1} + + pat bgt + leaving + cmi INT32 + zgt $1 + + pat zge /* Branch if signed top >= 0 */ + with TRISTATE_ALL+GPR STACK + gen + move %1, C0 + bc IFFALSE, LT, {LABEL, $1} + + pat bge + leaving + cmi INT32 + zge $1 + + pat zlt /* Branch if signed top < 0 */ + with TRISTATE_ALL+GPR STACK + gen + move %1, C0 + bc IFTRUE, LT, {LABEL, $1} + + pat blt + leaving + cmi INT32 + zlt $1 + + pat zle /* Branch if signed top >= 0 */ + with TRISTATE_ALL+GPR STACK + gen + move %1, C0 + bc IFFALSE, GT, {LABEL, $1} + + pat ble + leaving + cmi INT32 + zle $1 + + +/* Compare and jump */ + + pat cmi /* Signed tristate compare */ + with CONST GPR + yields {TRISTATE_RC_S, %2, %1.val} + with GPR GPR + yields {TRISTATE_RR_S, %2, %1} + + pat cmu /* Unsigned tristate compare */ + with CONST GPR + yields {TRISTATE_RC_U, %2, %1.val} + with GPR GPR + yields {TRISTATE_RR_U, %2, %1} + + pat cmp /* Compare pointers */ + leaving + cmu INT32 + + pat cms $1==INT32 /* Compare blocks (word sized) */ + leaving + cmi INT32 + + + + +/* Other branching and labelling */ + + pat lab topeltsize($1)==4 && !fallthrough($1) + gen + labeldef $1 + yields R3 + + pat lab topeltsize($1)==4 && fallthrough($1) + with GPR3 + gen + labeldef $1 + yields %1 + + pat lab topeltsize($1)!=4 + with STACK + kills ALL + gen + labeldef $1 + + pat bra topeltsize($1)==4 /* Unconditional jump with TOS GPRister */ + with GPR3 STACK + gen + b {LABEL, $1} + + pat bra topeltsize($1)!=4 /* Unconditional jump without TOS GPRister */ + with STACK + gen + b {LABEL, $1} + + + +/* Miscellaneous */ + + pat cal /* Call procedure */ + with STACK + kills ALL + gen + bl {LABEL, $1} + + pat cai /* Call procedure indirect */ + with GPR STACK + kills ALL + gen + mtspr CTR, %1 + bcctrl ALWAYS, {CONST, 0}, {CONST, 0} + + pat lfr $1==INT32 /* Load function result, word */ + yields R3 + + pat lfr $1==INT64 /* Load function result, double-word */ + yields R4 R3 + + pat ret $1==0 /* Return from procedure */ + gen + return + b {LABEL, ".ret"} + + pat ret $1==INT32 /* Return from procedure, word */ + with GPR3 + gen + return + b {LABEL, ".ret"} + + pat ret $1==INT64 /* Return from procedure, double-word */ + with GPR3 GPR4 + gen + return + b {LABEL, ".ret"} + + pat blm /* Block move constant length */ + with GPR GPR STACK + uses REG + gen + move {CONST, $1}, %a + stwu %a, {GPRINDIRECT, SP, 0-4} + stwu %2, {GPRINDIRECT, SP, 0-4} + stwu %1, {GPRINDIRECT, SP, 0-4} + bl {LABEL, "_memmove"} + addi SP, SP, {CONST, 12} + + pat bls /* Block move variable length */ + with GPR GPR GPR STACK + gen + stwu %1, {GPRINDIRECT, SP, 0-4} + stwu %3, {GPRINDIRECT, SP, 0-4} + stwu %2, {GPRINDIRECT, SP, 0-4} + bl {LABEL, "_memmove"} + addi SP, SP, {CONST, 12} + + pat csa /* Array-lookup switch */ + with GPR3 GPR4 STACK + gen + b {LABEL, ".csa"} + + pat csb /* Table-lookup switch */ + with GPR3 GPR4 STACK + gen + b {LABEL, ".csb"} + + + +/* EM specials */ + + pat fil /* Set current filename */ + leaving + lae $1 + ste ".filename" + + pat lin /* Set current line number */ + leaving + loc $1 + ste ".linenumber" + + pat lni /* Increment line number */ + leaving + ine ".linenumber" + + pat lim /* Load EM trap ignore mask */ + leaving + lde ".ignmask" + + pat sim /* Store EM trap ignore mask */ + leaving + ste ".ignmask" + + pat trp /* Raise EM trap */ + with GPR3 + gen + bl {LABEL, ".trap"} + + pat sig /* Set trap handler */ + leaving + ste ".trppc" + + pat rtt /* Return from trap */ + leaving + ret 0 + + pat lxl $1==0 /* Load FP */ + leaving + lor 0 + + pat lxl $1==1 /* Load caller's FP */ + leaving + lxl 0 + dch + + pat dch /* FP -> caller FP */ + with GPR + uses reusing %1, REG + gen + lwz %a, {GPRINDIRECT, %1, FP_OFFSET} + yields %a + + pat lpb /* Convert FP to argument address */ + leaving + adp EM_BSIZE + + pat lxa /* Load caller's SP */ + leaving + lxl $1 + lpb + + pat gto /* longjmp */ + uses REG + gen + move {LABEL, $1}, %a + move {IND_RC_W, %a, 8}, FP + move {IND_RC_W, %a, 4}, SP + move {IND_RC_W, %a, 0}, %a + mtspr CTR, %a + bcctr ALWAYS, {CONST, 0}, {CONST, 0} + +#if 0 + + pat gto /* longjmp */ + with STACK + gen + ld {LABEL, $1+2} + wspec {CONST, 1} + ld {LABEL, $1+4} + wspec {CONST, 0} + ld {LABEL, $1+0} + wspec {CONST, 2} + + pat str $1==1 /* Store special GPRister */ + with GPR0 + gen + wspec {CONST, $1} + +#endif + + pat lor $1==0 /* Load FP */ + uses REG + gen + move FP, %a + yields %a + + pat lor $1==1 /* Load SP */ + uses REG + gen + move SP, %a + yields %a + + pat lor $1==2 /* Load HP */ + leaving + loe ".reghp" + + pat str $1==0 /* Store FP */ + with GPR + gen + move %1, FP + + pat str $1==1 /* Store SP */ + with GPR + gen + move %1, SP + + pat str $1==2 /* Store HP */ + leaving + ste ".reghp" + + pat ass /* Adjust stack by variable amount */ + with CONST + gen + move {SUM_RC, SP, %1.val}, {GPRE, SP} + with GPR + gen + move {SUM_RR, SP, %1}, {GPRE, SP} + + pat asp /* Adjust stack by constant amount */ + leaving + loc $1 + ass + diff --git a/mach/vc4/test/opcodes.s b/mach/vc4/test/opcodes.s new file mode 100644 index 000000000..894a7540e --- /dev/null +++ b/mach/vc4/test/opcodes.s @@ -0,0 +1,77 @@ +# +/* + * VideoCore IV assembler test file + * © 2013 David Given + * This file is redistributable under the terms of the 3-clause BSD license. + * See the file 'Copying' in the root of the distribution for the full text. + */ + +.sect .text +.sect .rom +.sect .data +.sect .bss +.sect .text + +main: + nop + rti + + b r0 + b r31 + bl r0 + bl r31 + tbb r0 + tbb r15 + tbs r0 + tbs r15 + + mov r0, r1 + cmn r0, r1 + add r0, r1 + bic r0, r1 + mul r0, r1 + eor r0, r1 + sub r0, r1 + and r0, r1 + mvn r0, r1 + ror r0, r1 + cmp r0, r1 + rsb r0, r1 + btst r0, r1 + or r0, r1 + extu r0, r1 + max r0, r1 + bset r0, r1 + min r0, r1 + bclr r0, r1 + adds2 r0, r1 + bchg r0, r1 + adds4 r0, r1 + adds8 r0, r1 + adds16 r0, r1 + exts r0, r1 + neg r0, r1 + lsr r0, r1 + clz r0, r1 + lsl r0, r1 + brev r0, r1 + asr r0, r1 + abs r0, r1 + + mov r0, #31 + cmn r0, #31 + add r0, #31 + bic r0, #31 + mul r0, #31 + eor r0, #31 + sub r0, #31 + and r0, #31 + mvn r0, #31 + ror r0, #31 + cmp r0, #31 + rsb r0, #31 + btst r0, #31 + or r0, #31 + extu r0, #31 + max r0, #31 + diff --git a/plat/rpi/build.mk b/plat/rpi/build.mk new file mode 100644 index 000000000..20aed87f7 --- /dev/null +++ b/plat/rpi/build.mk @@ -0,0 +1,47 @@ +# Build script for Raspberry Pi bare-metal executables (using the +# VideoCore IV processor, not the ARM). +# +# © 2013 David Given +# This file is redistributable under the terms of the 3-clause BSD license. +# See the file 'Copying' in the root of the distribution for the full text. + +ARCH := vc4 +PLATFORM := rpi +OPTIMISATION := -O + +D := plat/rpi/ + +platform-headers := \ + ack/config.h + +platform-libsys := \ + _hol0.s \ + +ifeq (x,y) + errno.s \ + _sys_rawread.s \ + _sys_rawwrite.s \ + open.c \ + creat.c \ + close.c \ + read.c \ + write.c \ + brk.c \ + getpid.c \ + kill.c \ + isatty.c \ + lseek.c \ + time.c \ + signal.c +endif + +$(eval $(call build-platform)) + +define build-rpi-boot-impl + $(call reset) + $(call ackfile, $D/boot.s) + $(call installto, $(PLATIND)/$(PLATFORM)/boot.o) +endef + +#(eval $(build-rpi-boot-impl)) + diff --git a/plat/rpi/descr b/plat/rpi/descr new file mode 100644 index 000000000..41dfc400f --- /dev/null +++ b/plat/rpi/descr @@ -0,0 +1,69 @@ +# $Source$ +# $State$ +# $Revision$ + +var w=2 +var p=2 +var s=2 +var l=4 +var f=4 +var d=8 +var ARCH=vc4 +var PLATFORM=rpi +var PLATFORMDIR={EM}/share/ack/{PLATFORM} +var CPP_F=-D__unix +var ALIGN=-a0:1 -a1:1 -a2:1 -a3:1 +var MACHOPT_F=-m8 + +# Override the setting in fe so that files compiled for this platform can see +# the platform-specific headers. + +var C_INCLUDES=-I{PLATFORMDIR}/include -I{EM}/share/ack/include/ansi + +name be + from .m.g + to .s + program {EM}/lib/ack/{PLATFORM}/ncg + args < + stdout + need .e +end +name as + from .s.so + to .o + program {EM}/lib/ack/{PLATFORM}/as + args - -o > < + prep cond +end +name led + from .o.a + to .out + program {EM}/lib/ack/em_led + mapflag -l* LNAME={PLATFORMDIR}/lib* + mapflag -i SEPID=-b1:0 + mapflag -fp FLOATS={EM}/{ILIB}fp + args {ALIGN} {SEPID?} \ + (.e:{HEAD}={PLATFORMDIR}/boot.o) \ + ({RTS}:.ocm.b={PLATFORMDIR}/c-ansi.o) \ + ({RTS}:.c={PLATFORMDIR}/c-ansi.o) \ + ({RTS}:.mod={PLATFORMDIR}/modula2.o) \ + ({RTS}:.p={PLATFORMDIR}/pascal.o) \ + -o > < \ + (.p:{TAIL}={PLATFORMDIR}/libpascal.a) \ + (.b:{TAIL}={PLATFORMDIR}/libbasic.a) \ + (.mod:{TAIL}={PLATFORMDIR}/libmodula2.a) \ + (.ocm:{TAIL}={PLATFORMDIR}/liboccam.a) \ + (.ocm.b.mod.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ + {FLOATS?} \ + (.e:{TAIL}={PLATFORMDIR}/libem.a \ + {PLATFORMDIR}/libsys.a \ + {PLATFORMDIR}/libend.a) + linker +end +name cv + from .out + to .img + program {EM}/bin/aslod + args < > + outfile raspberrypi.bin +end diff --git a/plat/rpi/include/ack/config.h b/plat/rpi/include/ack/config.h new file mode 100644 index 000000000..fd2c48cba --- /dev/null +++ b/plat/rpi/include/ack/config.h @@ -0,0 +1,11 @@ +/* + * Raspberry Pi support library for the ACK + * © 2013 David Given + * This file is redistributable under the terms of the 3-clause BSD license. + * See the file 'Copying' in the root of the distribution for the full text. + */ + +#ifndef _ACK_CONFIG_H +#define _ACK_CONFIG_H + +#endif diff --git a/plat/rpi/include/unistd.h b/plat/rpi/include/unistd.h new file mode 100644 index 000000000..ddd8739d3 --- /dev/null +++ b/plat/rpi/include/unistd.h @@ -0,0 +1,73 @@ +/* + * Raspberry Pi support library for the ACK + * © 2013 David Given + * This file is redistributable under the terms of the 3-clause BSD license. + * See the file 'Copying' in the root of the distribution for the full text. + */ + +#ifndef _UNISTD_H +#define _UNISTD_H + +#include + +/* Types */ + +typedef int pid_t; +typedef int mode_t; + +/* Constants for file access (open and friends) */ + +enum +{ + O_ACCMODE = 0x3, + + O_RDONLY = 0, + O_WRONLY = 1, + O_RDWR = 2, + + O_CREAT = 0100, + O_TRUNC = 01000, + O_APPEND = 02000, + O_NONBLOCK = 04000 +}; + +/* Special variables */ + +extern char** environ; + +/* Implemented system calls */ + +extern void _exit(int); +extern pid_t getpid(void); +extern void* sbrk(intptr_t increment); +extern int isatty(int d); +extern off_t lseek(int fildes, off_t offset, int whence); +extern int close(int d); +extern int open(const char* path, int access, ...); +extern int creat(const char* path, mode_t mode); +extern int read(int fd, void* buffer, size_t count); +extern int write(int fd, void* buffer, size_t count); + +/* Unimplemented system calls (these are just prototypes to let the library + * compile). */ + +extern int fcntl(int fd, int op, ...); + +/* Signal handling */ + +typedef int sig_atomic_t; + +#define SIG_ERR ((sighandler_t) -1) /* Error return. */ +#define SIG_DFL ((sighandler_t) 0) /* Default action. */ +#define SIG_IGN ((sighandler_t) 1) /* Ignore signal. */ + +#define SIGABRT 6 /* Abort (ANSI) */ +#define SIGILL 11 /* Illegal instruction */ + +#define _NSIG 32 /* Biggest signal number + 1 + (not including real-time signals). */ +typedef void (*sighandler_t)(int); +extern sighandler_t signal(int signum, sighandler_t handler); +extern int raise(int signum); + +#endif diff --git a/plat/rpi/libsys/_hol0.s b/plat/rpi/libsys/_hol0.s new file mode 100644 index 000000000..eed00817d --- /dev/null +++ b/plat/rpi/libsys/_hol0.s @@ -0,0 +1,22 @@ +# +/* + * Raspberry Pi support library for the ACK + * © 2013 David Given + * This file is redistributable under the terms of the 3-clause BSD license. + * See the file 'Copying' in the root of the distribution for the full text. + */ + +! Declare segments (the order is important). + +.sect .text +.sect .rom +.sect .data +.sect .bss + +.sect .bss + +! This data block is used to store information about the current line number +! and file. + +.define hol0 +.comm hol0, 8 diff --git a/plat/rpi/libsys/_sys_rawread.s b/plat/rpi/libsys/_sys_rawread.s new file mode 100644 index 000000000..02edba21a --- /dev/null +++ b/plat/rpi/libsys/_sys_rawread.s @@ -0,0 +1,26 @@ +# +/* + * Raspberry Pi support library for the ACK + * © 2013 David Given + * This file is redistributable under the terms of the 3-clause BSD license. + * See the file 'Copying' in the root of the distribution for the full text. + */ + +! Declare segments (the order is important). + +.sect .text +.sect .rom +.sect .data +.sect .bss + +.sect .text + +! Reads a single byte. + +.define __sys_rawread +__sys_rawread: + xorb ah, ah + int 0x16 + xorb ah, ah + ret + \ No newline at end of file diff --git a/plat/rpi/libsys/_sys_rawwrite.s b/plat/rpi/libsys/_sys_rawwrite.s new file mode 100644 index 000000000..a424574d7 --- /dev/null +++ b/plat/rpi/libsys/_sys_rawwrite.s @@ -0,0 +1,32 @@ +# +/* + * Raspberry Pi support library for the ACK + * © 2013 David Given + * This file is redistributable under the terms of the 3-clause BSD license. + * See the file 'Copying' in the root of the distribution for the full text. + */ + +! Declare segments (the order is important). + +.sect .text +.sect .rom +.sect .data +.sect .bss + +.sect .text + +! Writes a single byte to the console. + +.define __sys_rawwrite +.extern __sys_rawwrite + +__sys_rawwrite: + push bp + mov bp, sp + + movb al, 4(bp) + movb ah, 0x0E + mov bx, 0x0007 + int 0x10 + jmp .cret + \ No newline at end of file diff --git a/plat/rpi/libsys/brk.c b/plat/rpi/libsys/brk.c new file mode 100644 index 000000000..cff32b9a9 --- /dev/null +++ b/plat/rpi/libsys/brk.c @@ -0,0 +1,45 @@ +/* + * Raspberry Pi support library for the ACK + * © 2013 David Given + * This file is redistributable under the terms of the 3-clause BSD license. + * See the file 'Copying' in the root of the distribution for the full text. + */ + +#include +#include +#include + +#define OUT_OF_MEMORY (void*)(-1) /* sbrk returns this on failure */ +#define STACK_BUFFER 128 /* number of bytes to leave for stack */ + +extern char _end[1]; +static char* current = _end; + +int brk(void* newend) +{ + /* This variable is used to figure out the current stack pointer, + * by taking its address. */ + char dummy; + char* p = newend; + + if ((p > (&dummy - STACK_BUFFER)) || + (p < _end)) + return -1; + + current = p; + return 0; +} + +void* sbrk(intptr_t increment) +{ + char* old; + + if (increment == 0) + return current; + + old = current; + if (brk(old + increment) < 0) + return OUT_OF_MEMORY; + + return old; +} diff --git a/plat/rpi/libsys/close.c b/plat/rpi/libsys/close.c new file mode 100644 index 000000000..60fa0f96b --- /dev/null +++ b/plat/rpi/libsys/close.c @@ -0,0 +1,16 @@ +/* + * Raspberry Pi support library for the ACK + * © 2013 David Given + * This file is redistributable under the terms of the 3-clause BSD license. + * See the file 'Copying' in the root of the distribution for the full text. + */ + +#include +#include +#include + +int close(int fd) +{ + errno = EBADF; + return -1; +} diff --git a/plat/rpi/libsys/creat.c b/plat/rpi/libsys/creat.c new file mode 100644 index 000000000..7c009e6a0 --- /dev/null +++ b/plat/rpi/libsys/creat.c @@ -0,0 +1,17 @@ +/* + * Raspberry Pi support library for the ACK + * © 2013 David Given + * This file is redistributable under the terms of the 3-clause BSD license. + * See the file 'Copying' in the root of the distribution for the full text. + */ + +#include +#include +#include +#include "libsys.h" + +int open(const char* path, int access, ...) +{ + errno = EACCES; + return -1; +} diff --git a/plat/rpi/libsys/errno.s b/plat/rpi/libsys/errno.s new file mode 100644 index 000000000..a2e1f8b55 --- /dev/null +++ b/plat/rpi/libsys/errno.s @@ -0,0 +1,31 @@ +# +/* + * Raspberry Pi support library for the ACK + * © 2013 David Given + * This file is redistributable under the terms of the 3-clause BSD license. + * See the file 'Copying' in the root of the distribution for the full text. + */ + +! Declare segments (the order is important). + +.sect .text +.sect .rom +.sect .data +.sect .bss + +#define D(e) .define e; e + +.sect .data + +! Define various ACK error numbers. Note that these are *not* ANSI C +! errnos, and are used for different purposes. + +D(ERANGE) = 1 +D(ESET) = 2 +D(EIDIVZ) = 6 +D(EHEAP) = 17 +D(EILLINS) = 18 +D(EODDZ) = 19 +D(ECASE) = 20 +D(EBADMON) = 25 + diff --git a/plat/rpi/libsys/getpid.c b/plat/rpi/libsys/getpid.c new file mode 100644 index 000000000..0ae1f6154 --- /dev/null +++ b/plat/rpi/libsys/getpid.c @@ -0,0 +1,15 @@ +/* + * Raspberry Pi support library for the ACK + * © 2013 David Given + * This file is redistributable under the terms of the 3-clause BSD license. + * See the file 'Copying' in the root of the distribution for the full text. + */ + +#include +#include +#include + +pid_t getpid(void) +{ + return 0; +} diff --git a/plat/rpi/libsys/isatty.c b/plat/rpi/libsys/isatty.c new file mode 100644 index 000000000..83837ba9c --- /dev/null +++ b/plat/rpi/libsys/isatty.c @@ -0,0 +1,15 @@ +/* + * Raspberry Pi support library for the ACK + * © 2013 David Given + * This file is redistributable under the terms of the 3-clause BSD license. + * See the file 'Copying' in the root of the distribution for the full text. + */ + +#include +#include +#include + +int isatty(int fd) +{ + return 1; +} diff --git a/plat/rpi/libsys/kill.c b/plat/rpi/libsys/kill.c new file mode 100644 index 000000000..bacc405df --- /dev/null +++ b/plat/rpi/libsys/kill.c @@ -0,0 +1,16 @@ +/* + * Raspberry Pi support library for the ACK + * © 2013 David Given + * This file is redistributable under the terms of the 3-clause BSD license. + * See the file 'Copying' in the root of the distribution for the full text. + */ + +#include +#include +#include + +int kill(pid_t pid, int sig) +{ + errno = EINVAL; + return -1; +} diff --git a/plat/rpi/libsys/libsys.h b/plat/rpi/libsys/libsys.h new file mode 100644 index 000000000..e9bff7e1a --- /dev/null +++ b/plat/rpi/libsys/libsys.h @@ -0,0 +1,18 @@ +/* + * Raspberry Pi support library for the ACK + * © 2013 David Given + * This file is redistributable under the terms of the 3-clause BSD license. + * See the file 'Copying' in the root of the distribution for the full text. + */ + +#ifndef LIBSYS_H +#define LIBSYS_H + +extern void _sys_rawwrite(unsigned char b); +extern unsigned char _sys_rawread(void); + +extern void _sys_write_tty(char c); + +/* extern int _sys_ttyflags; */ + +#endif diff --git a/plat/rpi/libsys/lseek.c b/plat/rpi/libsys/lseek.c new file mode 100644 index 000000000..9a487d747 --- /dev/null +++ b/plat/rpi/libsys/lseek.c @@ -0,0 +1,16 @@ +/* + * Raspberry Pi support library for the ACK + * © 2013 David Given + * This file is redistributable under the terms of the 3-clause BSD license. + * See the file 'Copying' in the root of the distribution for the full text. + */ + +#include +#include +#include + +off_t lseek(int fd, off_t offset, int whence) +{ + errno = EINVAL; + return -1; +} diff --git a/plat/rpi/libsys/open.c b/plat/rpi/libsys/open.c new file mode 100644 index 000000000..cbdc30ec1 --- /dev/null +++ b/plat/rpi/libsys/open.c @@ -0,0 +1,16 @@ +/* + * Raspberry Pi support library for the ACK + * © 2013 David Given + * This file is redistributable under the terms of the 3-clause BSD license. + * See the file 'Copying' in the root of the distribution for the full text. + */ + +#include +#include +#include +#include "libsys.h" + +int creat(const char* path, int mode) +{ + return open(path, O_CREAT|O_WRONLY|O_TRUNC, mode); +} diff --git a/plat/rpi/libsys/read.c b/plat/rpi/libsys/read.c new file mode 100644 index 000000000..476689320 --- /dev/null +++ b/plat/rpi/libsys/read.c @@ -0,0 +1,45 @@ +/* + * Raspberry Pi support library for the ACK + * © 2013 David Given + * This file is redistributable under the terms of the 3-clause BSD license. + * See the file 'Copying' in the root of the distribution for the full text. + */ + +#include +#include +#include +#include "libsys.h" + +int read(int fd, void* buffer, size_t count) +{ + char i; + + /* We're only allowed to read from fd 0, 1 or 2. */ + + if ((fd < 0) || (fd > 2)) + { + errno = EBADF; + return -1; + } + + /* Empty buffer? */ + + if (count == 0) + return 0; + + /* Read one byte. */ + + i = _sys_rawread(); +#if 0 + if ((i == '\r') && !(_sys_ttyflags & RAW)) + i = '\n'; + if (_sys_ttyflags & ECHO) + _sys_write_tty(i); +#endif + if (i == '\r') + i = '\n'; + _sys_write_tty(i); + + *(char*)buffer = i; + return 1; +} diff --git a/plat/rpi/libsys/signal.c b/plat/rpi/libsys/signal.c new file mode 100644 index 000000000..10a2ded29 --- /dev/null +++ b/plat/rpi/libsys/signal.c @@ -0,0 +1,17 @@ +/* + * Raspberry Pi support library for the ACK + * © 2013 David Given + * This file is redistributable under the terms of the 3-clause BSD license. + * See the file 'Copying' in the root of the distribution for the full text. + */ + +#include +#include +#include +#include +#include "libsys.h" + +sighandler_t signal(int signum, sighandler_t handler) +{ + return SIG_DFL; +} diff --git a/plat/rpi/libsys/time.c b/plat/rpi/libsys/time.c new file mode 100644 index 000000000..e448a33d0 --- /dev/null +++ b/plat/rpi/libsys/time.c @@ -0,0 +1,19 @@ +/* + * Raspberry Pi support library for the ACK + * © 2013 David Given + * This file is redistributable under the terms of the 3-clause BSD license. + * See the file 'Copying' in the root of the distribution for the full text. + */ + +#include +#include +#include +#include +#include "libsys.h" + +time_t time(time_t* t) +{ + if (t) + *t = 0; + return 0; +} diff --git a/plat/rpi/libsys/write.c b/plat/rpi/libsys/write.c new file mode 100644 index 000000000..9a765b04c --- /dev/null +++ b/plat/rpi/libsys/write.c @@ -0,0 +1,50 @@ +/* + * Raspberry Pi support library for the ACK + * © 2013 David Given + * This file is redistributable under the terms of the 3-clause BSD license. + * See the file 'Copying' in the root of the distribution for the full text. + */ + +#include +#include +#include +#include "libsys.h" + +void _sys_write_tty(char c) +{ + _sys_rawwrite(c); +#if 0 + if ((c == '\n') && !(_sys_ttyflags & RAW)) + _sys_rawwrite('\r'); +#endif + if (c == '\n') + _sys_rawwrite('\r'); +} + +int write(int fd, void* buffer, size_t count) +{ + int i; + char* p = buffer; + + /* We're only allowed to write to fd 0, 1 or 2. */ + + if ((fd < 0) || (fd > 2)) + { + errno = EBADF; + return -1; + } + + /* Write all data. */ + + i = 0; + while (i < count) + { + _sys_write_tty(*p++); + + i++; + } + + /* No failures. */ + + return count; +}