OpenCores
URL https://opencores.org/ocsvn/raptor64/raptor64/trunk

Subversion Repositories raptor64

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /raptor64/trunk/software/c64/source
    from Rev 36 to Rev 37
    Reverse comparison

Rev 36 → Rev 37

/GenerateFunction.c
0,0 → 1,241
// ============================================================================
// (C) 2012 Robert Finch
// All Rights Reserved.
// robfinch<remove>@opencores.org
//
// C64 - Raptor64 'C' derived language compiler
// - 64 bit CPU
//
// This source file is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file 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 this program. If not, see <http://www.gnu.org/licenses/>.
//
// ============================================================================
//
#include <stdio.h>
#include <string.h>
#include "c.h"
#include "expr.h"
#include "Statement.h"
#include "gen.h"
#include "cglbdec.h"
 
extern int breaklab;
extern int contlab;
extern int retlab;
extern int throwlab;
 
extern int lastsph;
extern char *semaphores[20];
 
extern TYP stdfunc;
 
void GenerateReturn(SYM *sym, Statement *stmt);
 
 
// Generate a function body.
//
void GenerateFunction(SYM *sym, Statement *stmt)
{
char buf[20];
char *bl;
 
throwlab = retlab = contlab = breaklab = -1;
lastsph = 0;
memset(semaphores,0,sizeof(semaphores));
throwlab = nextlabel++;
while( lc_auto & 7 ) /* round frame size to word */
++lc_auto;
if (sym->IsInterrupt) {
GenerateTriadic(op_subui,0,makereg(30),makereg(30),make_immed(30*8));
GenerateDiadic(op_sm,0,make_indirect(30), make_mask(0x9FFFFFFE));
}
if (!sym->IsNocall) {
GenerateTriadic(op_subui,0,makereg(30),makereg(30),make_immed(24));
// For a leaf routine don't bother to store the link register or exception link register.
if (sym->IsLeaf)
GenerateDiadic(op_sw,0,makereg(27),make_indirect(30));
else {
GenerateDiadic(op_sm, 0, make_indirect(30), make_mask(0x98000000));
GenerateDiadic(op_lea,0,makereg(28),make_label(throwlab));
}
GenerateDiadic(op_mov,0,makereg(27),makereg(30));
if (lc_auto)
GenerateTriadic(op_subui,0,makereg(30),makereg(30),make_immed(lc_auto));
}
if (optimize)
opt1(stmt);
GenerateStatement(stmt);
GenerateReturn(sym,0);
// Generate code for the hidden default catch
GenerateLabel(throwlab);
if (sym->IsLeaf){
if (sym->DoesThrow) {
GenerateDiadic(op_mov,0,makereg(31),makereg(28));
GenerateDiadic(op_bra,0,make_label(retlab),NULL); // goto regular return cleanup code
}
}
else {
GenerateDiadic(op_lw,0,makereg(31),make_indexed(16,27)); // load throw return address from stack into LR
GenerateDiadic(op_sw,0,makereg(31),make_indirect(27)); // and store it back (so it can be loaded with the lm)
GenerateDiadic(op_bra,0,make_label(retlab),NULL); // goto regular return cleanup code
}
}
 
 
// Generate a return statement.
//
void GenerateReturn(SYM *sym, Statement *stmt)
{
AMODE *ap;
int nn;
int lab1;
 
if( stmt != NULL && stmt->exp != NULL )
{
initstack();
ap = GenerateExpression(stmt->exp,F_REG|F_IMMED,8);
// Force return value into register 1
if( ap->preg != 1 ) {
if (ap->mode == am_immed)
GenerateTriadic(op_ori, 0, makereg(1),makereg(0),ap);
else
GenerateDiadic(op_mov, 0, makereg(1),ap);
}
}
// Generate the return code only once. Branch to the return code for all returns.
if( retlab == -1 )
{
retlab = nextlabel++;
GenerateLabel(retlab);
// Unlock any semaphores that may have been set
for (nn = lastsph - 1; nn >= 0; nn--)
GenerateDiadic(op_sb,0,makereg(0),make_string(semaphores[nn]));
if (sym->IsNocall) // nothing to do for nocall convention
return;
// Restore registers used as register variables.
if( save_mask != 0 ) {
if (bitsset(save_mask) < 2) {
for (nn = 31; nn >=1 ; nn--)
if (save_mask & (1 << nn))
GenerateTriadic(op_lw,0,makereg(nn),make_indirect(30),NULL);
}
else
GenerateTriadic(op_lm,0,make_indirect(30),make_mask(save_mask),NULL);
}
// Unlink the stack
// For a leaf routine the link register and exception link register doesn't need to be saved/restored.
GenerateDiadic(op_mov,0,makereg(30),makereg(27));
if (sym->IsLeaf)
GenerateDiadic(op_lw,0,makereg(27),make_indirect(30));
else
GenerateDiadic(op_lm,0,make_indirect(30),make_mask(0x98000000));
//if (isOscall) {
// GenerateDiadic(op_move,0,makereg(0),make_string("_TCBregsave"));
// gen_regrestore();
//}
// Generate the return instruction. For the Pascal calling convention pop the parameters
// from the stack.
if (sym->IsInterrupt) {
GenerateTriadic(op_addui,0,makereg(30),makereg(30),make_immed(24));
GenerateDiadic(op_lm,0,make_indirect(30),make_mask(0x9FFFFFFE));
GenerateTriadic(op_addui,0,makereg(30),makereg(30),make_immed(popcnt(0x9FFFFFFE)*8));
GenerateDiadic(op_iret,0,NULL,NULL);
return;
}
if (sym->IsPascal)
GenerateDiadic(op_ret,0,make_immed(24+sym->NumParms * 8),NULL);
else
GenerateDiadic(op_ret,0,make_immed(24),NULL);
}
// Just branch to the already generated stack cleanup code.
else {
GenerateDiadic(op_bra,0,make_label(retlab),0);
}
}
 
// push the operand expression onto the stack.
//
static void GeneratePushParameter(ENODE *ep, int i, int n)
{
AMODE *ap;
ap = GenerateExpression(ep,F_REG,8);
GenerateDiadic(op_sw,0,ap,make_indexed((n-i)*8-8,30));
ReleaseTempRegister(ap);
}
 
// push entire parameter list onto stack
//
static int GeneratePushParameterList(ENODE *plist)
{
ENODE *st = plist;
int i,n;
// count the number of parameters
for(n = 0; plist != NULL; n++ )
plist = plist->p[1];
// move stack pointer down by number of parameters
if (st)
GenerateTriadic(op_subui,0,makereg(30),makereg(30),make_immed(n*8));
plist = st;
for(i = 0; plist != NULL; i++ )
{
GeneratePushParameter(plist->p[0],i,n);
plist = plist->p[1];
}
return i;
}
 
AMODE *GenerateFunctionCall(ENODE *node, int flags)
{
AMODE *ap, *result;
SYM *sym;
int i;
int msk;
 
msk = SaveTempRegs();
sym = NULL;
i = GeneratePushParameterList(node->p[1]);
// Call the function
if( node->p[0]->nodetype == en_nacon ) {
GenerateDiadic(op_call,0,make_offset(node->p[0]),NULL);
sym = gsearch(node->p[0]->sp);
}
else
{
ap = GenerateExpression(node->p[0],F_REG,8);
ap->mode = am_ind;
GenerateDiadic(op_jal,0,makereg(31),ap);
ReleaseTempRegister(ap);
}
// Pop parameters off the stack
if (i!=0) {
if (sym) {
if (!sym->IsPascal)
GenerateTriadic(op_addui,0,makereg(30),makereg(30),make_immed(i * 8));
}
else
GenerateTriadic(op_addui,0,makereg(30),makereg(30),make_immed(i * 8));
}
RestoreTempRegs(msk);
result = GetTempRegister();
if( result->preg != 1 || (flags & F_REG) == 0 )
if (sym) {
if (sym->tp->btp->type==bt_void)
;
else
GenerateTriadic(op_or,0,result,makereg(1),makereg(0));
}
else
GenerateTriadic(op_or,0,result,makereg(1),makereg(0));
return result;
}
 
/ParseEnumDeclaration.c
0,0 → 1,88
#include <stdio.h>
#include <string.h>
#include "c.h"
#include "expr.h"
#include "Statement.h"
#include "gen.h"
#include "cglbdec.h"
 
/*******************************************************
Modified to support Raptor64 'C64' language
by Robert Finch
robfinch@opencores.org
*******************************************************/
 
extern TABLE tagtable;
extern TYP *head;
extern TYP stdconst;
 
void enumbody(TABLE *table);
 
void ParseEnumDeclaration(TABLE *table)
{
SYM *sp;
TYP *tp;
if( lastst == id) {
if((sp = search(lastid,&tagtable)) == NULL) {
sp = allocSYM();
sp->tp = allocTYP();
sp->tp->type = bt_enum;
sp->tp->size = 2;
sp->tp->lst.head = 0;
sp->tp->btp = 0;
sp->storage_class = sc_type;
sp->name = litlate(lastid);
sp->tp->sname = sp->name;
NextToken();
if( lastst != begin)
error(ERR_INCOMPLETE);
else {
insert(sp,&tagtable);
NextToken();
ParseEnumerationList(table);
}
}
else
NextToken();
head = sp->tp;
}
else {
tp = allocTYP(); // fix here
tp->type = bt_short;
if( lastst != begin)
error(ERR_INCOMPLETE);
else {
NextToken();
ParseEnumerationList(table);
}
head = tp;
}
}
 
void ParseEnumerationList(TABLE *table)
{
int evalue;
SYM *sp;
evalue = 0;
while(lastst == id) {
sp = allocSYM();
sp->name = litlate(lastid);
sp->storage_class = sc_const;
sp->tp = &stdconst;
insert(sp,table);
NextToken();
if (lastst==assign) {
NextToken();
sp->value.i = GetIntegerExpression();
evalue = sp->value.i+1;
}
else
sp->value.i = evalue++;
if( lastst == comma)
NextToken();
else if(lastst != end)
break;
}
needpunc(end);
}
 
/List.c
0,0 → 1,170
#include <stdio.h>
#include "c.h"
#include "expr.h"
#include "gen.h"
#include "cglbdec.h"
 
/*
* 68000 C compiler
*
* Copyright 1984, 1985, 1986 Matthew Brandt.
* all commercial rights reserved.
*
* This compiler is intended as an instructive tool for personal use. Any
* use for profit without the written consent of the author is prohibited.
*
* This compiler may be distributed freely for non-commercial use as long
* as this notice stays intact. Please forward any enhancements or questions
* to:
*
* Matthew Brandt
* Box 920337
* Norcross, Ga 30092
*/
/*******************************************************
Modified to support Raptor64 'C64' language
by Robert Finch
robfinch@opencores.org
*******************************************************/
 
void ListTable(TABLE *t, int i);
 
void put_typedef(int td)
{
fprintf(list,td ? " 1 " : " - ");
}
 
void put_sc(int scl)
{ switch(scl) {
case sc_static:
fprintf(list,"Static ");
break;
case sc_auto:
fprintf(list,"Auto ");
break;
case sc_global:
fprintf(list,"Global ");
break;
case sc_external:
fprintf(list,"External ");
break;
case sc_type:
fprintf(list,"Type ");
break;
case sc_const:
fprintf(list,"Constant ");
break;
case sc_member:
fprintf(list,"Member ");
break;
case sc_label:
fprintf(list,"Label");
break;
case sc_ulabel:
fprintf(list,"Undefined label");
break;
}
}
 
void put_ty(TYP *tp)
{ if(tp == 0)
return;
switch(tp->type) {
case bt_byte:
fprintf(list,"Byte");
break;
case bt_char:
fprintf(list,"Char");
break;
case bt_short:
fprintf(list,"Short");
break;
case bt_enum:
fprintf(list,"enum ");
goto ucont;
case bt_long:
fprintf(list,"Long");
break;
case bt_unsigned:
fprintf(list,"unsigned long");
break;
case bt_float:
fprintf(list,"Float");
break;
case bt_double:
fprintf(list,"Double");
break;
case bt_pointer:
if( tp->val_flag == 0)
fprintf(list,"Pointer to ");
else
fprintf(list,"Array of ");
put_ty(tp->btp);
break;
case bt_union:
fprintf(list,"union ");
goto ucont;
case bt_struct:
fprintf(list,"struct ");
ucont: if(tp->sname == 0)
fprintf(list,"<no name> ");
else
fprintf(list,"%s ",tp->sname);
break;
case bt_ifunc:
case bt_func:
fprintf(list,"Function returning ");
put_ty(tp->btp);
break;
}
}
 
void list_var(SYM *sp, int i)
{ int j;
for(j = i; j; --j)
fprintf(list," ");
if (sp->name == NULL)
fprintf(list,"%-10s =%06x ","<unnamed>",sp->value.u);
else
fprintf(list,"%-10s =%06x ",sp->name,sp->value.u);
if( sp->storage_class == sc_external)
fprintf(output,"\textern\t%s\n",sp->name);
else if( sp->storage_class == sc_global )
fprintf(output,";\tglobal\t%s\n",sp->name);
put_typedef(sp->storage_class==sc_typedef);
put_sc(sp->storage_class);
put_ty(sp->tp);
fprintf(list,"\n");
if(sp->tp == 0)
return;
if((sp->tp->type == bt_struct || sp->tp->type == bt_union) &&
sp->storage_class == sc_type)
ListTable(&(sp->tp->lst),i+1);
}
 
void ListTable(TABLE *t, int i)
{
SYM *sp;
int nn;
 
if (t==&gsyms[0]) {
for (nn = 0; nn < 257; nn++) {
t = &gsyms[nn];
sp = t->head;
while(sp != NULL) {
list_var(sp,i);
sp = sp->next;
}
}
}
else {
sp = t->head;
while(sp != NULL) {
list_var(sp,i);
sp = sp->next;
}
}
}
 
 

/ParseExpressions.c
0,0 → 1,1145
#include <stdio.h>
#include "c.h"
#include "expr.h"
#include "Statement.h"
#include "gen.h"
#include "cglbdec.h"
 
/*
* 68000 C compiler
*
* Copyright 1984, 1985, 1986 Matthew Brandt.
* all commercial rights reserved.
*
* This compiler is intended as an instructive tool for personal use. Any
* use for profit without the written consent of the author is prohibited.
*
* This compiler may be distributed freely for non-commercial use as long
* as this notice stays intact. Please forward any enhancements or questions
* to:
*
* Matthew Brandt
* Box 920337
* Norcross, Ga 30092
*/
/*******************************************************
Modified to support Raptor64 'C64' language
by Robert Finch
robfinch@opencores.org
*******************************************************/
 
TYP stdint = { bt_long, bt_long, 0, FALSE, FALSE, FALSE, 0,0,8, {0, 0}, 0, 0 };
TYP stduint = { bt_long, bt_long, 0, TRUE, FALSE, FALSE, 0,0,8, {0, 0}, 0, 0 };
TYP stdlong = { bt_long, bt_long, 0, FALSE, FALSE, FALSE, 0,0,8, {0, 0}, 0, 0 };
TYP stdulong = { bt_long, bt_long, 0, TRUE, FALSE, FALSE, 0,0,8, {0, 0}, 0, 0 };
TYP stdshort = { bt_short, bt_short, 0, FALSE, FALSE, FALSE, 0,0,4, {0, 0}, 0, 0 };
TYP stdushort = { bt_short, bt_short, 0, TRUE, FALSE, FALSE, 0,0,4, {0, 0}, 0, 0 };
TYP stdchar = {bt_char, bt_char, 0, FALSE, FALSE, FALSE, 0,0,2, {0, 0}, 0, 0 };
TYP stduchar = {bt_char, bt_char, 0, TRUE, FALSE, FALSE, 0,0,2, {0, 0}, 0, 0 };
TYP stdbyte = {bt_byte, bt_byte, 0, FALSE, FALSE, FALSE, 0,0,1, {0, 0}, 0, 0 };
TYP stdubyte = {bt_byte, bt_byte, 0, TRUE, FALSE, FALSE, 0,0,1, {0, 0}, 0, 0 };
TYP stdstring = {bt_pointer, bt_pointer, 1, FALSE, FALSE, FALSE, 0,0,4, {0, 0}, &stdchar, 0};
TYP stdfunc = {bt_func, bt_func, 1, FALSE, FALSE, FALSE, 0,0,0, {0, 0}, &stdint, 0};
extern TYP *head; /* shared with ParseSpecifier */
extern TYP *tail;
 
/*
* expression evaluation
*
* this set of routines builds a parse tree for an expression.
* no code is generated for the expressions during the build,
* this is the job of the codegen module. for most purposes
* expression() is the routine to call. it will allow all of
* the C operators. for the case where the comma operator is
* not valid (function parameters for instance) call NonCommaExpression().
*
* each of the routines returns a pointer to a describing type
* structure. each routine also takes one parameter which is a
* pointer to an expression node by reference (address of pointer).
* the completed expression is returned in this pointer. all
* routines return either a pointer to a valid type or NULL if
* the hierarchy of the next operator is too low or the next
* symbol is not part of an expression.
*/
 
TYP *expression(); /* forward ParseSpecifieraration */
TYP *NonCommaExpression(); /* forward ParseSpecifieraration */
TYP *ParseUnaryExpression(); /* forward ParseSpecifieraration */
 
/*
* build an expression node with a node type of nt and values
* v1 and v2.
*/
ENODE *makenode(int nt, ENODE *v1, ENODE *v2)
{
ENODE *ep;
ep = (ENODE *)xalloc(sizeof(ENODE));
ep->nodetype = nt;
ep->constflag = FALSE;
ep->etype = bt_void;
ep->esize = -1;
ep->p[0] = v1;
ep->p[1] = v2;
return ep;
}
 
ENODE *makesnode(int nt, char *v1)
{
ENODE *ep;
ep = (ENODE *)xalloc(sizeof(ENODE));
ep->nodetype = nt;
ep->constflag = FALSE;
ep->etype = bt_void;
ep->esize = -1;
ep->sp = v1;
return ep;
}
 
ENODE *makenodei(int nt, ENODE *v1, __int64 i)
{
ENODE *ep;
ep = (ENODE *)xalloc(sizeof(ENODE));
ep->nodetype = nt;
ep->constflag = FALSE;
ep->etype = bt_void;
ep->esize = -1;
ep->i = i;
ep->p[0] = v1;
ep->p[1] = NULL;
return ep;
}
 
ENODE *makeinode(int nt, __int64 v1)
{
ENODE *ep;
ep = (ENODE *)xalloc(sizeof(ENODE));
ep->nodetype = nt;
ep->constflag = TRUE;
ep->etype = bt_void;
ep->esize = -1;
ep->i = v1;
return ep;
}
 
void PromoteConstFlag(ENODE *ep)
{
ep->constflag = ep->p[0]->constflag && ep->p[1]->constflag;
}
 
/*
* build the proper dereference operation for a node using the
* type pointer tp.
*/
TYP *deref(ENODE **node, TYP *tp)
{
switch( tp->type ) {
case bt_byte:
if (tp->isUnsigned)
*node = makenode(en_ub_ref,*node,NULL);
else
*node = makenode(en_b_ref,*node,NULL);
(*node)->esize = tp->size;
(*node)->etype = tp->type;
tp = &stdint;
break;
case bt_char:
case bt_enum:
if (tp->isUnsigned)
*node = makenode(en_uc_ref,*node,NULL);
else
*node = makenode(en_c_ref,*node,NULL);
(*node)->esize = tp->size;
(*node)->etype = tp->type;
tp = &stdchar;
break;
case bt_short:
*node = makenode(en_h_ref,*node,NULL);
(*node)->esize = tp->size;
(*node)->etype = tp->type;
tp = &stdint;
break;
case bt_long:
case bt_pointer:
case bt_unsigned:
(*node)->esize = tp->size;
(*node)->etype = tp->type;
*node = makenode(en_w_ref,*node,NULL);
break;
case bt_bitfield:
if (tp->isUnsigned){
if (tp->size==1)
*node = makenode(en_ubfieldref, *node, NULL);
else if (tp->size==2)
*node = makenode(en_ucfieldref, *node, NULL);
else if (tp->size==4)
*node = makenode(en_uhfieldref, *node, NULL);
else
*node = makenode(en_wfieldref, *node, NULL);
}
else {
if (tp->size==1)
*node = makenode(en_bfieldref, *node, NULL);
else if (tp->size==2)
*node = makenode(en_cfieldref, *node, NULL);
else if (tp->size==4)
*node = makenode(en_hfieldref, *node, NULL);
else
*node = makenode(en_wfieldref, *node, NULL);
}
(*node)->bit_width = tp->bit_width;
(*node)->bit_offset = tp->bit_offset;
/*
* maybe it should be 'unsigned'
*/
(*node)->etype = stdint.type;
(*node)->esize = tp->size;
tp = &stdint;
break;
default:
error(ERR_DEREF);
break;
}
return tp;
}
 
/*
* nameref will build an expression tree that references an
* identifier. if the identifier is not in the global or
* local symbol table then a look-ahead to the next character
* is done and if it indicates a function call the identifier
* is coerced to an external function name. non-value references
* generate an additional level of indirection.
*/
TYP *nameref(ENODE **node)
{
SYM *sp;
TYP *tp;
sp = gsearch(lastid);
if( sp == NULL ) {
while( isspace(lastch) )
getch();
if( lastch == '(') {
++global_flag;
sp = allocSYM();
sp->tp = &stdfunc;
sp->name = litlate(lastid);
sp->storage_class = sc_external;
insert(sp,&gsyms);
--global_flag;
tp = &stdfunc;
*node = makesnode(en_nacon,sp->name);
(*node)->constflag = TRUE;
}
else {
tp = NULL;
error(ERR_UNDEFINED);
}
}
else {
if( (tp = sp->tp) == NULL ) {
error(ERR_UNDEFINED);
return NULL; /* guard against untyped entries */
}
switch( sp->storage_class ) {
case sc_static:
*node = makeinode(en_labcon,sp->value.i);
(*node)->constflag = TRUE;
break;
case sc_global:
case sc_external:
*node = makesnode(en_nacon,sp->name);
(*node)->constflag = TRUE;
break;
case sc_const:
*node = makeinode(en_icon,sp->value.i);
(*node)->constflag = TRUE;
break;
default: /* auto and any errors */
if( sp->storage_class != sc_auto)
error(ERR_ILLCLASS);
*node = makeinode(en_autocon,sp->value.i);
break;
}
if( tp->val_flag == FALSE)
tp = deref(node,tp);
}
NextToken();
return tp;
}
 
/*
* ArgumentList will build a list of parameter expressions in
* a function call and return a pointer to the last expression
* parsed. since parameters are generally pushed from right
* to left we get just what we asked for...
*/
ENODE *ArgumentList()
{
struct ENODE *ep1, *ep2;
ep1 = 0;
while( lastst != closepa)
{
NonCommaExpression(&ep2); /* evaluate a parameter */
ep1 = makenode(en_void,ep2,ep1);
if( lastst != comma)
break;
NextToken();
}
return ep1;
}
 
/*
* return 1 if st in set of [ kw_char, kw_short, kw_long, kw_int,
* kw_float, kw_double, kw_struct, kw_union ]
*/
static int IsIntrinsicType(int st)
{
return st == kw_byte || st==kw_char || st == kw_short || st == kw_int || st==kw_void ||
st == kw_long || st == kw_float || st == kw_double || st==kw_enum ||
st == kw_struct || st == kw_union || st== kw_unsigned || st==kw_signed;
}
 
int IsBeginningOfTypecast(int st)
{
SYM *sp;
if (st==id) {
sp = search(lastid,&gsyms[0]);
if (sp)
return sp->storage_class==sc_typedef;
return FALSE;
}
else
return IsIntrinsicType(st);
}
 
/*
* primary will parse a primary expression and set the node pointer
* returning the type of the expression parsed. primary expressions
* are any of:
* id
* constant
* string
* ( expression )
* primary[ expression ]
* primary.id
* primary->id
* primary( parameter list )
*/
TYP *ParsePrimaryExpression(ENODE **node)
{
ENODE *pnode, *qnode, *rnode, *snode;
SYM *sp;
TYP *tptr;
switch( lastst ) {
 
case id:
tptr = nameref(&pnode);
break;
case iconst:
tptr = &stdint;
pnode = makeinode(en_icon,ival);
pnode->constflag = TRUE;
NextToken();
break;
case sconst:
tptr = &stdstring;
pnode = makenode(en_labcon,stringlit(laststr),NULL);
pnode->constflag = TRUE;
NextToken();
break;
 
case openpa:
NextToken();
if( !IsBeginningOfTypecast(lastst) ) {
tptr = expression(&pnode);
needpunc(closepa);
}
else { /* cast operator */
ParseSpecifier(0); /* do cast ParseSpecifieraration */
ParseDeclarationPrefix(FALSE);
tptr = head;
needpunc(closepa);
if( ParseUnaryExpression(&pnode) == NULL ) {
error(ERR_IDEXPECT);
tptr = NULL;
}
}
break;
 
default:
return NULL;
}
for(;;) {
switch( lastst ) {
case openbr: /* build a subscript reference */
if (tptr==NULL) {
error(ERR_UNDEFINED);
goto fini;
}
if( tptr->type != bt_pointer )
error(ERR_NOPOINTER);
else
tptr = tptr->btp;
NextToken();
qnode = makeinode(en_icon,tptr->size);
qnode->constflag = TRUE;
expression(&rnode);
/*
* we could check the type of the expression here...
*/
qnode = makenode(en_mulu,qnode,rnode);
qnode->constflag = rnode->constflag && qnode->p[0]->constflag;
pnode = makenode(en_add,qnode,pnode);
pnode->constflag = qnode->constflag && pnode->p[1]->constflag;
////snode = makenode(en_mul,qnode,rnode);
////snode->constflag = rnode->constflag && snode->p[0]->constflag;
////pnode = makenode(en_add,snode,pnode);
////pnode->constflag = snode->constflag && pnode->p[1]->constflag;
if( tptr->val_flag == FALSE )
tptr = deref(&pnode,tptr);
needpunc(closebr);
break;
 
case pointsto:
if (tptr==NULL) {
error(ERR_UNDEFINED);
goto fini;
}
if( tptr->type != bt_pointer )
error(ERR_NOPOINTER);
else
tptr = tptr->btp;
if( tptr->val_flag == FALSE )
pnode = makenode(en_w_ref,pnode,NULL);
/*
* fall through to dot operation
*/
case dot:
NextToken(); /* past -> or . */
if( lastst != id )
error(ERR_IDEXPECT);
else {
sp = search(lastid,&tptr->lst);
if( sp == NULL )
error(ERR_NOMEMBER);
else {
tptr = sp->tp;
qnode = makeinode(en_icon,sp->value.i);
qnode->constflag = TRUE;
pnode = makenode(en_add,pnode,qnode);
pnode->constflag = pnode->p[0]->constflag;
if( tptr->val_flag == FALSE )
tptr = deref(&pnode,tptr);
}
NextToken(); /* past id */
}
break;
 
case openpa: /* function reference */
NextToken();
if( tptr->type != bt_func && tptr->type != bt_ifunc )
error(ERR_NOFUNC);
else
tptr = tptr->btp;
currentFn->IsLeaf = FALSE;
pnode = makenode(en_fcall,pnode,ArgumentList());
needpunc(closepa);
break;
 
default:
goto fini;
}
}
fini: *node = pnode;
return tptr;
}
 
/*
* this function returns true if the node passed is an IsLValue.
* this can be qualified by the fact that an IsLValue must have
* one of the dereference operators as it's top node.
*/
int IsLValue(ENODE *node)
{
switch( node->nodetype ) {
case en_b_ref:
case en_c_ref:
case en_h_ref:
case en_w_ref:
case en_ub_ref:
case en_uc_ref:
case en_uh_ref:
case en_uw_ref:
case en_wfieldref:
case en_uwfieldref:
case en_bfieldref:
case en_ubfieldref:
case en_cfieldref:
case en_ucfieldref:
case en_hfieldref:
case en_uhfieldref:
return TRUE;
case en_cbc:
case en_cbh:
case en_cbw:
case en_cch:
case en_ccw:
case en_chw:
return IsLValue(node->p[0]);
}
return FALSE;
}
 
/*
* ParseUnaryExpression evaluates unary expressions and returns the type of the
* expression evaluated. unary expressions are any of:
*
* primary
* primary++
* primary--
* !unary
* ~unary
* ++unary
* --unary
* -unary
* *unary
* &unary
* (typecast)unary
* sizeof(typecast)
* typenum(typecast)
*
*/
TYP *ParseUnaryExpression(ENODE **node)
{
TYP *tp, *tp1;
ENODE *ep1, *ep2;
int flag;
__int64 i;
 
flag = 0;
switch( lastst ) {
case autodec:
flag = 1;
/* fall through to common increment */
case autoinc:
NextToken();
tp = ParseUnaryExpression(&ep1);
if( tp == NULL ) {
error(ERR_IDEXPECT);
return NULL;
}
if( IsLValue(ep1)) {
if( tp->type == bt_pointer )
ep2 = makeinode(en_icon,tp->btp->size);
else
ep2 = makeinode(en_icon,1);
ep2->constflag = TRUE;
ep1 = makenode(flag ? en_assub : en_asadd,ep1,ep2);
}
else
error(ERR_LVALUE);
break;
 
case minus:
NextToken();
tp = ParseUnaryExpression(&ep1);
if( tp == NULL ) {
error(ERR_IDEXPECT);
return NULL;
}
ep1 = makenode(en_uminus,ep1,NULL);
ep1->constflag = ep1->p[0]->constflag;
break;
 
case not:
NextToken();
tp = ParseUnaryExpression(&ep1);
if( tp == NULL ) {
error(ERR_IDEXPECT);
return NULL;
}
ep1 = makenode(en_not,ep1,NULL);
ep1->constflag = ep1->p[0]->constflag;
break;
 
case compl:
NextToken();
tp = ParseUnaryExpression(&ep1);
if( tp == NULL ) {
error(ERR_IDEXPECT);
return 0;
}
ep1 = makenode(en_compl,ep1,NULL);
ep1->constflag = ep1->p[0]->constflag;
break;
 
case star:
NextToken();
tp = ParseUnaryExpression(&ep1);
if( tp == NULL ) {
error(ERR_IDEXPECT);
return NULL;
}
if( tp->btp == NULL )
error(ERR_DEREF);
else
tp = tp->btp;
if( tp->val_flag == FALSE )
tp = deref(&ep1,tp);
break;
 
case and:
NextToken();
tp = ParseUnaryExpression(&ep1);
if( tp == NULL ) {
error(ERR_IDEXPECT);
return NULL;
}
if( IsLValue(ep1))
ep1 = ep1->p[0];
tp1 = allocTYP();
tp1->size = 8;
tp1->type = bt_pointer;
tp1->btp = tp;
tp1->val_flag = FALSE;
tp1->lst.head = NULL;
tp1->sname = NULL;
tp = tp1;
break;
 
case kw_sizeof:
NextToken();
needpunc(openpa);
tp = head;
tp1 = tail;
ParseSpecifier(0);
ParseDeclarationPrefix(FALSE);
if( head != NULL )
ep1 = makeinode(en_icon,head->size);
else {
error(ERR_IDEXPECT);
ep1 = makeinode(en_icon,1);
}
head = tp;
tail = tp1;
ep1->constflag = TRUE;
tp = &stdint;
needpunc(closepa);
break;
 
case kw_typenum:
NextToken();
needpunc(openpa);
tp = head;
tp1 = tail;
ParseSpecifier(0);
ParseDeclarationPrefix(FALSE);
if( head != NULL )
ep1 = makeinode(en_icon,GetTypeHash(head));
else {
error(ERR_IDEXPECT);
ep1 = makeinode(en_icon,1);
}
head = tp;
tail = tp1;
ep1->constflag = TRUE;
tp = &stdint;
needpunc(closepa);
break;
 
default:
tp = ParsePrimaryExpression(&ep1);
if( tp != NULL ) {
if( tp->type == bt_pointer )
i = tp->btp->size;
else
i = 1;
if( lastst == autoinc) {
if( IsLValue(ep1) )
ep1 = makenodei(en_ainc,ep1,i);
else
error(ERR_LVALUE);
NextToken();
}
else if( lastst == autodec ) {
if( IsLValue(ep1) )
ep1 = makenodei(en_adec,ep1,i);
else
error(ERR_LVALUE);
NextToken();
}
}
break;
}
*node = ep1;
return tp;
}
 
/*
* forcefit will coerce the nodes passed into compatable
* types and return the type of the resulting expression.
*/
TYP *forcefit(ENODE **node1,TYP *tp1,ENODE **node2,TYP *tp2)
{
switch( tp1->type ) {
case bt_char:
case bt_uchar:
if (tp2->type == bt_long) {
if (tp1->isUnsigned)
return &stdulong;
else
return &stdlong;
}
if (tp2->type == bt_short) {
if (tp1->isUnsigned)
return &stdushort;
else
return &stdshort;
}
if (tp2->type == bt_pointer)
return tp2;
return tp1; // char
case bt_short:
case bt_ushort:
if (tp2->type == bt_long) {
if (tp1->isUnsigned)
return &stdulong;
else
return &stdlong;
}
if (tp2->type == bt_pointer)
return tp2;
return tp1;
case bt_long:
case bt_ulong:
if( tp2->type == bt_pointer )
return tp2;
return tp1;
case bt_pointer:
if( isscalar(tp2) || tp2->type == bt_pointer)
return tp1;
break;
case bt_unsigned:
if( tp2->type == bt_pointer )
return tp2;
else if( isscalar(tp2) )
return tp1;
break;
}
error( ERR_MISMATCH );
return tp1;
}
 
/*
* this function returns true when the type of the argument is
* one of char, short, unsigned, or long.
*/
int isscalar(TYP *tp)
{
return
tp->type == bt_byte ||
tp->type == bt_char ||
tp->type == bt_short ||
tp->type == bt_long ||
tp->type == bt_uchar ||
tp->type == bt_ushort ||
tp->type == bt_ulong ||
tp->type == bt_unsigned;
}
 
/*
* multops parses the multiply priority operators. the syntax of
* this group is:
*
* unary
* multop * unary
* multop / unary
* multop % unary
*/
TYP *multops(struct ENODE **node)
{
struct ENODE *ep1, *ep2;
TYP *tp1, *tp2;
int oper;
tp1 = ParseUnaryExpression(&ep1);
if( tp1 == 0 )
return 0;
while( lastst == star || lastst == divide || lastst == modop ) {
oper = lastst;
NextToken(); /* move on to next unary op */
tp2 = ParseUnaryExpression(&ep2);
if( tp2 == 0 ) {
error(ERR_IDEXPECT);
*node = ep1;
return tp1;
}
tp1 = forcefit(&ep1,tp1,&ep2,tp2);
switch( oper ) {
case star:
if( tp1->isUnsigned )
ep1 = makenode(en_mulu,ep1,ep2);
else
ep1 = makenode(en_mul,ep1,ep2);
break;
case divide:
if( tp1->isUnsigned )
ep1 = makenode(en_udiv,ep1,ep2);
else
ep1 = makenode(en_div,ep1,ep2);
break;
case modop:
if( tp1->isUnsigned )
ep1 = makenode(en_umod,ep1,ep2);
else
ep1 = makenode(en_mod,ep1,ep2);
break;
}
PromoteConstFlag(ep1);
}
*node = ep1;
return tp1;
}
 
/*
* addops handles the addition and subtraction operators.
*/
TYP *addops(ENODE **node)
{
ENODE *ep1, *ep2, *ep3;
TYP *tp1, *tp2;
int oper;
 
tp1 = multops(&ep1);
if( tp1 == NULL )
return NULL;
while( lastst == plus || lastst == minus ) {
oper = (lastst == plus);
NextToken();
tp2 = multops(&ep2);
if( tp2 == 0 ) {
error(ERR_IDEXPECT);
*node = ep1;
return tp1;
}
if( tp1->type == bt_pointer ) {
tp2 = forcefit(0,&stdint,&ep2,tp2);
ep3 = makeinode(en_icon,tp1->btp->size);
ep3->constflag = TRUE;
ep2 = makenode(en_mulu,ep3,ep2);
ep2->constflag = ep2->p[1]->constflag;
}
else if( tp2->type == bt_pointer ) {
tp1 = forcefit(0,&stdint,&ep1,tp1);
ep3 = makeinode(en_icon,tp2->btp->size);
ep3->constflag = TRUE;
ep1 = makenode(en_mulu,ep3,ep1);
ep1->constflag = ep1->p[1]->constflag;
}
tp1 = forcefit(&ep1,tp1,&ep2,tp2);
ep1 = makenode( oper ? en_add : en_sub,ep1,ep2);
PromoteConstFlag(ep1);
}
*node = ep1;
return tp1;
}
 
/*
* shiftop handles the shift operators << and >>.
*/
TYP *shiftop(ENODE **node)
{
struct ENODE *ep1, *ep2;
TYP *tp1, *tp2;
int oper;
tp1 = addops(&ep1);
if( tp1 == 0)
return 0;
while( lastst == lshift || lastst == rshift) {
oper = (lastst == lshift);
NextToken();
tp2 = addops(&ep2);
if( tp2 == 0 )
error(ERR_IDEXPECT);
else {
tp1 = forcefit(&ep1,tp1,&ep2,tp2);
if (tp1->isUnsigned)
ep1 = makenode(oper ? en_shl : en_shru,ep1,ep2);
else
ep1 = makenode(oper ? en_shl : en_shr,ep1,ep2);
PromoteConstFlag(ep1);
}
}
*node = ep1;
return tp1;
}
 
/*
* relation handles the relational operators < <= > and >=.
*/
TYP *relation(ENODE **node)
{ struct ENODE *ep1, *ep2;
TYP *tp1, *tp2;
int nt;
tp1 = shiftop(&ep1);
if( tp1 == 0 )
return 0;
for(;;) {
switch( lastst ) {
 
case lt:
if( tp1->isUnsigned )
nt = en_ult;
else
nt = en_lt;
break;
case gt:
if( tp1->isUnsigned )
nt = en_ugt;
else
nt = en_gt;
break;
case leq:
if( tp1->isUnsigned )
nt = en_ule;
else
nt = en_le;
break;
case geq:
if( tp1->isUnsigned )
nt = en_uge;
else
nt = en_ge;
break;
default:
goto fini;
}
NextToken();
tp2 = shiftop(&ep2);
if( tp2 == 0 )
error(ERR_IDEXPECT);
else {
tp1 = forcefit(&ep1,tp1,&ep2,tp2);
ep1 = makenode(nt,ep1,ep2);
PromoteConstFlag(ep1);
}
}
fini: *node = ep1;
return tp1;
}
 
/*
* equalops handles the equality and inequality operators.
*/
TYP *equalops(ENODE **node)
{
ENODE *ep1, *ep2;
TYP *tp1, *tp2;
int oper;
tp1 = relation(&ep1);
if( tp1 == NULL )
return NULL;
while( lastst == eq || lastst == neq ) {
oper = (lastst == eq);
NextToken();
tp2 = relation(&ep2);
if( tp2 == NULL )
error(ERR_IDEXPECT);
else {
tp1 = forcefit(&ep1,tp1,&ep2,tp2);
ep1 = makenode( oper ? en_eq : en_ne,ep1,ep2);
PromoteConstFlag(ep1);
}
}
*node = ep1;
return tp1;
}
 
/*
* binop is a common routine to handle all of the legwork and
* error checking for bitand, bitor, bitxor, andop, and orop.
*/
TYP *binop(ENODE **node, TYP *(*xfunc)(),int nt, int sy)
{
ENODE *ep1, *ep2;
TYP *tp1, *tp2;
tp1 = (*xfunc)(&ep1);
if( tp1 == 0 )
return 0;
while( lastst == sy ) {
NextToken();
tp2 = (*xfunc)(&ep2);
if( tp2 == 0 )
error(ERR_IDEXPECT);
else {
tp1 = forcefit(&ep1,tp1,&ep2,tp2);
ep1 = makenode(nt,ep1,ep2);
PromoteConstFlag(ep1);
}
}
*node = ep1;
return tp1;
}
 
TYP *bitand(ENODE **node)
/*
* the bitwise and operator...
*/
{ return binop(node,equalops,en_and,and);
}
 
TYP *bitxor(ENODE **node)
{ return binop(node,bitand,en_xor,uparrow);
}
 
TYP *bitor(ENODE **node)
{ return binop(node,bitxor,en_or,or);
}
 
TYP *andop(ENODE **node)
{ return binop(node,bitor,en_land,land);
}
 
TYP *orop(ENODE **node)
{
return binop(node,andop,en_lor,lor);
}
 
/*
* this routine processes the hook operator.
*/
TYP *conditional(ENODE **node)
{
TYP *tp1, *tp2, *tp3;
struct ENODE *ep1, *ep2, *ep3;
tp1 = orop(&ep1); /* get condition */
if( tp1 == NULL )
return NULL;
if( lastst == hook ) {
NextToken();
if( (tp2 = conditional(&ep2)) == NULL) {
error(ERR_IDEXPECT);
goto cexit;
}
needpunc(colon);
if( (tp3 = conditional(&ep3)) == NULL) {
error(ERR_IDEXPECT);
goto cexit;
}
tp1 = forcefit(&ep2,tp2,&ep3,tp3);
ep2 = makenode(en_void,ep2,ep3);
ep1 = makenode(en_cond,ep1,ep2);
}
cexit: *node = ep1;
return tp1;
}
 
/*
* asnop handles the assignment operators. currently only the
* simple assignment is implemented.
*/
TYP *asnop(ENODE **node)
{ struct ENODE *ep1, *ep2, *ep3;
TYP *tp1, *tp2;
int op;
tp1 = conditional(&ep1);
if( tp1 == 0 )
return 0;
for(;;) {
switch( lastst ) {
case assign:
op = en_assign;
ascomm: NextToken();
tp2 = asnop(&ep2);
ascomm2: if( tp2 == 0 || !IsLValue(ep1) )
error(ERR_LVALUE);
else {
tp1 = forcefit(&ep1,tp1,&ep2,tp2);
ep1 = makenode(op,ep1,ep2);
}
break;
case asplus:
op = en_asadd;
ascomm3: tp2 = asnop(&ep2);
if( tp1->type == bt_pointer ) {
ep3 = makeinode(en_icon,tp1->btp->size);
ep2 = makenode(en_mul,ep2,ep3);
}
goto ascomm;
case asminus:
op = en_assub;
goto ascomm3;
case astimes:
op = en_asmul;
goto ascomm;
case asdivide:
op = en_asdiv;
goto ascomm;
case asmodop:
op = en_asmod;
goto ascomm;
case aslshift:
op = en_aslsh;
goto ascomm;
case asrshift:
op = en_asrsh;
goto ascomm;
case asand:
op = en_asand;
goto ascomm;
case asor:
op = en_asor;
goto ascomm;
default:
goto asexit;
}
}
asexit: *node = ep1;
return tp1;
}
 
/*
* evaluate an expression where the comma operator is not legal.
*/
TYP *NonCommaExpression(ENODE **node)
{
TYP *tp;
tp = asnop(node);
if( tp == NULL )
*node = NULL;
return tp;
}
 
/*
* evaluate the comma operator. comma operators are kept as
* void nodes.
*/
TYP *commaop(ENODE **node)
{
TYP *tp1;
ENODE *ep1, *ep2;
tp1 = asnop(&ep1);
if( tp1 == NULL )
return NULL;
if( lastst == comma ) {
tp1 = commaop(&ep2);
if( tp1 == NULL ) {
error(ERR_IDEXPECT);
goto coexit;
}
ep1 = makenode(en_void,ep1,ep2);
}
coexit: *node = ep1;
return tp1;
}
 
/*
* evaluate an expression where all operators are legal.
*/
TYP *expression(ENODE **node)
{
TYP *tp;
tp = commaop(node);
if( tp == NULL )
*node = NULL;
return tp;
}
/Gen.h
0,0 → 1,57
/*
* code generation structures and constants
*/
 
#define F_REG 1 /* register direct mode allowed */
#define F_MEM 4 /* memory alterable modes allowed */
#define F_IMMED 8 /* immediate mode allowed */
#define F_ALT 7 /* alterable modes */
#define F_DALT 5 /* data alterable modes */
#define F_ALL 15 /* all modes allowed */
#define F_VOL 16 /* need volitile operand */
#define F_NOVALUE 32 /* dont need result value */
#define F_IMMED18 64 // 18-bit immediate constant
 
/* addressing mode structure */
 
typedef struct amode {
unsigned int mode : 4;
unsigned int preg : 6;
unsigned int sreg : 6;
unsigned int tempflag : 1;
int deep; /* stack depth on allocation */
struct enode *offset;
} AMODE;
 
/* output code structure */
 
struct ocode {
struct ocode *fwd, *back;
short opcode;
short length;
AMODE *oper1, *oper2, *oper3;
};
 
enum e_op {
op_move, op_add, op_addu, op_addi, op_sub, op_subi, op_mov,
op_muls, op_mulsi, op_mulu, op_divs, op_divsi, op_divu, op_and, op_andi,
op_or, op_ori, op_xor, op_xori, op_asr, op_shl, op_shr, op_shru,
op_shli, op_shri, op_shrui,
op_jmp, op_mului, op_mod, op_modu,
op_tas, op_bmi, op_subu, op_lwr, op_swc, op_loop, op_iret,
op_sext32,op_sext16,op_sext8, op_dw, op_cache,
op_subui, op_addui, op_sei,
op_sw, op_sh, op_sc, op_sb,
op_call, op_jal, op_beqi, op_bnei,
op_lw, op_lh, op_lc, op_lb, op_ret, op_sm, op_lm,
op_rts, op_bra, op_bf, op_beq, op_bne, op_blt, op_ble, op_bgt, op_bge,
op_bgtu, op_bgeu, op_bltu, op_bleu, op_bnr,
op_bhi, op_bhs, op_blo, op_bls, op_tst, op_ext, op_lea, op_swap,
op_neg, op_not, op_cmp, op_clr, op_link, op_unlk, op_label, op_ilabel,
op_pea, op_cmpi, op_dc, op_asm, op_stop, op_empty };
 
enum e_am {
am_reg, am_ind, am_ainc, am_adec, am_indx, am_indx2,
am_direct, am_immed, am_mask, am_none, am_indx3
};
 
/NextToken.c
0,0 → 1,570
#include <stdio.h>
#include "c.h"
#include "expr.h"
#include "gen.h"
#include "cglbdec.h"
 
/*
* 68000 C compiler
*
* Copyright 1984, 1985, 1986 Matthew Brandt.
* all commercial rights reserved.
*
* This compiler is intended as an instructive tool for personal use. Any
* use for profit without the written consent of the author is prohibited.
*
* This compiler may be distributed freely for non-commercial use as long
* as this notice stays intact. Please forward any enhancements or questions
* to:
*
* Matthew Brandt
* Box 920337
* Norcross, Ga 30092
*/
/*******************************************************
Modified to support Raptor64 'C64' language
by Robert Finch
robfinch@opencores.org
*******************************************************/
extern char *errtext(int);
 
int errno[80];
int numerrs;
char inpline[132];
int total_errors = 0;
char *lptr; /* shared with preproc */
FILE *inclfile[10]; /* shared with preproc */
int inclline[10]; /* shared with preproc */
int incldepth; /* shared with preproc */
char *linstack[20]; /* stack for substitutions */
char chstack[20]; /* place to save lastch */
int lstackptr = 0; /* substitution stack pointer */
 
int isalnum(char c)
{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
(c >= '0' && c <= '9');
}
 
int isidch(char c) { return isalnum(c) || c == '_' || c == '$'; }
int isspace(char c) { return c == ' ' || c == '\t' || c == '\n'; }
int isdigit(char c) { return (c >= '0' && c <= '9'); }
 
void initsym()
{
lptr = inpline;
inpline[0] = 0;
numerrs = 0;
total_errors = 0;
lineno = 0;
}
 
int getline(int listflag)
{
int rv;
 
if(lineno > 0 && listflag) {
fprintf(list,"%6d\t%s",lineno,inpline);
while(numerrs--)
fprintf(list," *** error %d: %s\n",errno[numerrs],errtext(errno[numerrs]));
numerrs = 0;
}
++lineno;
rv = (fgets(inpline,131,input) == NULL);
if( rv && incldepth > 0 ) {
fclose(input);
input = inclfile[--incldepth];
lineno = inclline[incldepth];
return getline(0);
}
if( rv )
return 1;
lptr = inpline;
if(inpline[0] == '#')
return preprocess();
return 0;
}
 
/*
* getch - basic get character routine.
*/
int getch()
{
while( (lastch = *lptr++) == '\0') {
if( lstackptr > 0 ) {
lptr = linstack[--lstackptr];
lastch = chstack[lstackptr];
return lastch;
}
if(getline(incldepth == 0))
return lastch = -1;
}
return lastch;
}
/*
* getid - get an identifier.
*
* identifiers are any isidch conglomerate
* that doesn't start with a numeric character.
* this set INCLUDES keywords.
*/
void getid()
{
register int i;
i = 0;
while(isidch(lastch)) {
if(i < 32)
lastid[i++] = lastch;
getch();
}
lastid[i] = '\0';
lastst = id;
}
/*
* getsch - get a character in a quoted string.
*
* this routine handles all of the escape mechanisms
* for characters in strings and character constants.
*/
int getsch() /* return an in-quote character */
{ register int i, j;
if(lastch == '\n')
return -1;
if(lastch != '\\') {
i = lastch;
getch();
return i;
}
getch(); /* get an escaped character */
if(isdigit(lastch)) {
i = 0;
for(j = i = 0;j < 3;++j) {
if(lastch <= '7' && lastch >= '0')
i = (i << 3) + lastch - '0';
else
break;
getch();
}
return i;
}
i = lastch;
getch();
switch(i) {
case '\n':
getch();
return getsch();
case 'b':
return '\b';
case 'f':
return '\f';
case 'n':
return '\n';
case 'r':
return '\r';
case 't':
return '\t';
default:
return i;
}
}
 
__int64 radix36(char c)
{
if(isdigit(c))
return c - '0';
if(c >= 'a' && c <= 'z')
return c - 'a' + 10;
if(c >= 'A' && c <= 'Z')
return c - 'A' + 10;
return -1;
}
/*
* getbase - get an integer in any base.
*/
void getbase(b)
{ register __int64 i, j;
i = 0;
while(isalnum(lastch)) {
if((j = radix36(lastch)) < b) {
i = i * b + j;
getch();
}
else break;
}
if (lastch=='L') // ignore a 'L'ong suffix
getch();
ival = i;
lastst = iconst;
}
/*
* getfrac - get fraction part of a floating number.
*/
void getfrac()
{
double frmul;
frmul = 0.1;
while(isdigit(lastch)) {
rval += frmul * (lastch - '0');
getch();
frmul *= 0.1;
}
}
/*
* getexp - get exponent part of floating number.
*
* this algorithm is primative but usefull. Floating
* exponents are limited to +/-255 but most hardware
* won't support more anyway.
*/
getexp()
{ double expo, exmul;
expo = 1.0;
if(lastst != rconst)
rval = ival;
if(lastch == '-') {
exmul = 0.1;
getch();
}
else
exmul = 10.0;
getbase(10);
if(ival > 255)
error(ERR_FPCON);
else
while(ival--)
expo *= exmul;
rval *= expo;
}
/*
* getnum - get a number from input.
*
* getnum handles all of the numeric input. it accepts
* decimal, octal, hexidecimal, and floating point numbers.
*/
getnum()
{ register int i;
i = 0;
if(lastch == '0') {
getch();
if(lastch == 'x' || lastch == 'X') {
getch();
getbase(16);
}
else getbase(8);
}
else {
getbase(10);
if(lastch == '.') {
getch();
rval = ival; /* float the integer part */
getfrac(); /* add the fractional part */
lastst = rconst;
}
if(lastch == 'e' || lastch == 'E') {
getch();
getexp(); /* get the exponent */
}
}
}
 
void SkipSpaces()
{
while( isspace(lastch) )
getch();
}
/*
* NextToken - get next symbol from input stream.
*
* NextToken is the basic lexical analyzer. It builds
* basic tokens out of the characters on the input
* stream and sets the following global variables:
*
* lastch: A look behind buffer.
* lastst: type of last symbol read.
* laststr: last string constant read.
* lastid: last identifier read.
* ival: last integer constant read.
* rval: last real constant read.
*
* NextToken should be called for all your input needs...
*/
void NextToken()
{ register int i, j;
SYM *sp;
restart: /* we come back here after comments */
SkipSpaces();
if( lastch == -1)
lastst = eof;
else if(isdigit(lastch))
getnum();
else if(isidch(lastch)) {
getid();
if( (sp = search(lastid,&defsyms)) != NULL ) {
linstack[lstackptr] = lptr;
chstack[lstackptr++] = lastch;
lptr = sp->value.s;
getch();
goto restart;
}
}
else switch(lastch) {
case '+':
getch();
if(lastch == '+') {
getch();
lastst = autoinc;
}
else if(lastch == '=') {
getch();
lastst = asplus;
}
else lastst = plus;
break;
case '-':
getch();
if(lastch == '-') {
getch();
lastst = autodec;
}
else if(lastch == '=') {
getch();
lastst = asminus;
}
else if(lastch == '>') {
getch();
lastst = pointsto;
}
else lastst = minus;
break;
case '*':
getch();
if(lastch == '=') {
getch();
lastst = astimes;
}
else lastst = star;
break;
case '/':
getch();
if(lastch == '=') {
getch();
lastst = asdivide;
}
else if(lastch == '*') {
getch();
for(;;) {
if(lastch == '*') {
getch();
if(lastch == '/') {
getch();
goto restart;
}
}
else
getch();
}
}
else if (lastch == '/') {
for(;;) {
getch();
if (lastch=='\n') {
getch();
goto restart;
}
}
}
else lastst = divide;
break;
case '^':
getch();
lastst = uparrow;
break;
case ';':
getch();
lastst = semicolon;
break;
case ':':
getch();
lastst = colon;
break;
case '=':
getch();
if(lastch == '=') {
getch();
lastst = eq;
}
else lastst = assign;
break;
case '>':
getch();
if(lastch == '=') {
getch();
lastst = geq;
}
else if(lastch == '>') {
getch();
if(lastch == '=') {
getch();
lastst = asrshift;
}
else lastst = rshift;
}
else lastst = gt;
break;
case '<':
getch();
if(lastch == '=') {
getch();
lastst = leq;
}
else if(lastch == '<') {
getch();
if(lastch == '=') {
getch();
lastst = aslshift;
}
else lastst = lshift;
}
else if (lastch == '>') {
getch();
lastst = neq;
}
else lastst = lt;
break;
case '\'':
getch();
ival = getsch(); /* get a string char */
if(lastch != '\'')
error(ERR_SYNTAX);
else
getch();
lastst = iconst;
break;
case '\"':
getch();
for(i = 0;i < MAX_STRLEN;++i) {
if(lastch == '\"')
break;
if((j = getsch()) == -1)
break;
else
laststr[i] = j;
}
laststr[i] = 0;
lastst = sconst;
if(lastch != '\"')
error(ERR_SYNTAX);
else
getch();
break;
case '!':
getch();
if(lastch == '=') {
getch();
lastst = neq;
}
else lastst = not;
break;
case '%':
getch();
if(lastch == '=') {
getch();
lastst = asmodop;
}
else lastst = modop;
break;
case '~':
getch();
lastst = compl;
break;
case '.':
getch();
lastst = dot;
if (lastch=='.') {
getch();
if (lastch=='.')
getch();
lastst = ellipsis;
}
break;
case ',':
getch();
lastst = comma;
break;
case '&':
getch();
if( lastch == '&') {
lastst = land;
getch();
}
else if( lastch == '=') {
lastst = asand;
getch();
}
else
lastst = and;
break;
case '|':
getch();
if(lastch == '|') {
lastst = lor;
getch();
}
else if( lastch == '=') {
lastst = asor;
getch();
}
else
lastst = or;
break;
case '(':
getch();
lastst = openpa;
break;
case ')':
getch();
lastst = closepa;
break;
case '[':
getch();
lastst = openbr;
break;
case ']':
getch();
lastst = closebr;
break;
case '{':
getch();
lastst = begin;
break;
case '}':
getch();
lastst = end;
break;
case '?':
getch();
lastst = hook;
break;
default:
getch();
error(ERR_ILLCHAR);
goto restart; /* get a real token */
}
if(lastst == id)
IdentifyKeyword();
}
 
void needpunc(enum e_sym p)
{
if( lastst == p)
NextToken();
else
error(ERR_PUNCT);
}
 

/GenerateStatement.c
0,0 → 1,748
#include <stdio.h>
#include "c.h"
#include "expr.h"
#include "Statement.h"
#include "gen.h"
#include "cglbdec.h"
 
/*
* 68000 C compiler
*
* Copyright 1984, 1985, 1986 Matthew Brandt.
* all commercial rights reserved.
*
* This compiler is intended as an instructive tool for personal use. Any
* use for profit without the written consent of the author is prohibited.
*
* This compiler may be distributed freely for non-commercial use as long
* as this notice stays intact. Please forward any enhancements or questions
* to:
*
* Matthew Brandt
* Box 920337
* Norcross, Ga 30092
*/
/*******************************************************
Modified to support Raptor64 'C64' language
by Robert Finch
robfinch@opencores.org
*******************************************************/
 
int breaklab;
int contlab;
int retlab;
int throwlab;
 
int lastsph;
char *semaphores[20];
 
extern TYP stdfunc;
 
 
int bitsset(int mask)
{
int nn,bs=0;
for (nn =0; nn < 32; nn++)
if (mask & (1 << nn)) bs++;
return bs;
}
 
AMODE *makereg(int r)
{
AMODE *ap;
ap = allocAmode();
ap->mode = am_reg;
ap->preg = r;
return ap;
}
 
/*
* generate the mask address structure.
*/
AMODE *make_mask(int mask)
{
AMODE *ap;
ap = allocAmode();
ap->mode = am_mask;
ap->offset = mask;
return ap;
}
 
/*
* make a direct reference to an immediate value.
*/
AMODE *make_direct(__int64 i)
{
return make_offset(makeinode(en_icon,i,0));
}
 
/*
* generate a direct reference to a string label.
*/
AMODE *make_strlab(char *s)
{
AMODE *ap;
ap = allocAmode();
ap->mode = am_direct;
ap->offset = makesnode(en_nacon,s);
return ap;
}
 
/*
* generate code to evaluate a while statement.
*/
void GenerateWhile(struct snode *stmt)
{
int lab1, lab2;
 
initstack(); /* initialize temp registers */
lab1 = contlab; /* save old continue label */
lab2 = breaklab; /* save old break label */
contlab = nextlabel++; /* new continue label */
GenerateLabel(contlab);
if( stmt->s1 != NULL ) /* has block */
{
breaklab = nextlabel++;
initstack();
GenerateFalseJump(stmt->exp,breaklab);
GenerateStatement(stmt->s1);
GenerateDiadic(op_bra,0,make_label(contlab),NULL);
GenerateLabel(breaklab);
breaklab = lab2; /* restore old break label */
}
else /* no loop code */
{
initstack();
GenerateTrueJump(stmt->exp,contlab);
}
contlab = lab1; /* restore old continue label */
}
 
/*
* generate code to evaluate an until statement.
*/
void GenerateUntil(Statement *stmt)
{
int lab1, lab2;
 
initstack(); /* initialize temp registers */
lab1 = contlab; /* save old continue label */
lab2 = breaklab; /* save old break label */
contlab = nextlabel++; /* new continue label */
GenerateLabel(contlab);
if( stmt->s1 != NULL ) /* has block */
{
breaklab = nextlabel++;
initstack();
GenerateTrueJump(stmt->exp,breaklab);
GenerateStatement(stmt->s1);
GenerateDiadic(op_bra,0,make_label(contlab),NULL);
GenerateLabel(breaklab);
breaklab = lab2; /* restore old break label */
}
else /* no loop code */
{
initstack();
GenerateFalseJump(stmt->exp,contlab);
}
contlab = lab1; /* restore old continue label */
}
 
 
// generate code to evaluate a for loop
//
void GenerateFor(struct snode *stmt)
{
int old_break, old_cont, exit_label, loop_label;
old_break = breaklab;
old_cont = contlab;
loop_label = nextlabel++;
exit_label = nextlabel++;
contlab = loop_label;
initstack();
if( stmt->initExpr != NULL )
GenerateExpression(stmt->initExpr,F_ALL | F_NOVALUE
,GetNaturalSize(stmt->initExpr));
GenerateLabel(loop_label);
initstack();
if( stmt->exp != NULL )
GenerateFalseJump(stmt->exp,exit_label);
if( stmt->s1 != NULL )
{
breaklab = exit_label;
GenerateStatement(stmt->s1);
}
initstack();
if( stmt->incrExpr != NULL )
GenerateExpression(stmt->incrExpr,F_ALL | F_NOVALUE,GetNaturalSize(stmt->incrExpr));
GenerateTriadic(op_bra,0,make_label(loop_label),NULL,NULL);
breaklab = old_break;
contlab = old_cont;
GenerateLabel(exit_label);
}
 
 
// generate code to evaluate a forever loop
//
void GenerateForever(Statement *stmt)
{
int old_break, old_cont, exit_label, loop_label;
old_break = breaklab;
old_cont = contlab;
loop_label = nextlabel++;
exit_label = nextlabel++;
contlab = loop_label;
GenerateLabel(loop_label);
if( stmt->s1 != NULL )
{
breaklab = exit_label;
GenerateStatement(stmt->s1);
}
GenerateDiadic(op_bra,0,make_label(loop_label),NULL);
breaklab = old_break;
contlab = old_cont;
GenerateLabel(exit_label);
}
 
/*
* generate code to evaluate an if statement.
*/
void GenerateIf(struct snode *stmt)
{ int lab1, lab2, oldbreak;
lab1 = nextlabel++; /* else label */
lab2 = nextlabel++; /* exit label */
oldbreak = breaklab; /* save break label */
initstack(); /* clear temps */
GenerateFalseJump(stmt->exp,lab1);
if( stmt->s1 != 0 && stmt->s1->next != 0 )
if( stmt->s2 != 0 )
breaklab = lab2;
else
breaklab = lab1;
GenerateStatement(stmt->s1);
if( stmt->s2 != 0 ) /* else part exists */
{
GenerateDiadic(op_bra,0,make_label(lab2),0);
GenerateLabel(lab1);
if( stmt->s2 == 0 || stmt->s2->next == 0 )
breaklab = oldbreak;
else
breaklab = lab2;
GenerateStatement(stmt->s2);
GenerateLabel(lab2);
}
else /* no else code */
GenerateLabel(lab1);
breaklab = oldbreak;
}
 
/*
* generate code for a do - while loop.
*/
void GenerateDo(struct snode *stmt)
{
int oldcont, oldbreak;
oldcont = contlab;
oldbreak = breaklab;
contlab = nextlabel++;
GenerateLabel(contlab);
if( stmt->s1 != 0 && stmt->s1->next != 0 )
{
breaklab = nextlabel++;
GenerateStatement(stmt->s1); /* generate body */
initstack();
GenerateTrueJump(stmt->exp,contlab);
GenerateLabel(breaklab);
}
else
{
GenerateStatement(stmt->s1);
initstack();
GenerateTrueJump(stmt->exp,contlab);
}
breaklab = oldbreak;
contlab = oldcont;
}
 
/*
* generate code for a do - while loop.
*/
void GenerateDoUntil(struct snode *stmt)
{
int oldcont, oldbreak;
oldcont = contlab;
oldbreak = breaklab;
contlab = nextlabel++;
GenerateLabel(contlab);
if( stmt->s1 != 0 && stmt->s1->next != 0 )
{
breaklab = nextlabel++;
GenerateStatement(stmt->s1); /* generate body */
initstack();
GenerateFalseJump(stmt->exp,contlab);
GenerateLabel(breaklab);
}
else
{
GenerateStatement(stmt->s1);
initstack();
GenerateFalseJump(stmt->exp,contlab);
}
breaklab = oldbreak;
contlab = oldcont;
}
 
/*
* generate a call to a library routine.
*/
void call_library(char *lib_name)
{
SYM *sp;
sp = gsearch(lib_name);
if( sp == NULL )
{
++global_flag;
sp = allocSYM();
sp->tp = &stdfunc;
sp->name = lib_name;
sp->storage_class = sc_external;
insert(sp,&gsyms);
--global_flag;
}
GenerateDiadic(op_call,0,make_strlab(lib_name),NULL);
}
 
/*
* generate a linear search switch statement.
*/
void GenerateSwitch(Statement *stmt)
{
int curlab;
int *bf;
int nn;
struct snode *defcase;
struct amode *ap;
curlab = nextlabel++;
defcase = 0;
initstack();
ap = GenerateExpression(stmt->exp,F_REG,4);
if( ap->preg != 0 )
GenerateTriadic(op_or,0,makereg(1),ap,makereg(0));
stmt = stmt->s1;
while( stmt != NULL )
{
if( stmt->s2 ) /* default case ? */
{
stmt->label = curlab;
defcase = stmt;
}
else
{
bf = stmt->label;
for (nn = bf[0]; nn >= 1; nn--)
GenerateTriadic(op_beq,0,makereg(1),make_immed(bf[nn]),make_label(curlab));
//GenerateDiadic(op_dw,0,make_label(curlab), make_direct(stmt->label));
stmt->label = curlab;
}
if( stmt->s1 != NULL && stmt->next != NULL )
curlab = nextlabel++;
stmt = stmt->next;
}
if( defcase == NULL )
GenerateTriadic(op_bra,0,make_label(breaklab),NULL,NULL);
else
GenerateTriadic(op_bra,0,make_label(defcase->label),NULL,NULL);
}
 
 
// generate all cases for a switch statement.
//
void GenerateCase(Statement *stmt)
{
while( stmt != NULL )
{
if( stmt->s1 != NULL )
{
GenerateLabel(stmt->label);
GenerateStatement(stmt->s1);
}
else if( stmt->next == NULL )
GenerateLabel(stmt->label);
stmt = stmt->next;
}
}
 
/*
* analyze and generate best switch statement.
*/
genxswitch(Statement *stmt)
{
int oldbreak;
oldbreak = breaklab;
breaklab = nextlabel++;
GenerateSwitch(stmt);
GenerateCase(stmt->s1);
GenerateLabel(breaklab);
breaklab = oldbreak;
}
 
int popcnt(int m)
{
int n;
int cnt;
 
cnt =0;
for (n = 0; n < 32; n = n + 1)
if (m & (1 << n)) cnt = cnt + 1;
return cnt;
}
/*
void gen_regsave()
{
int lab1;
 
lab1 = nextlabel++;
GenerateLabel(lab1);
GenerateDiadic(op_tas,1,make_strlab("sfRunningTCB"),NULL);
GenerateDiadic(op_bmi,0,make_label(lab1),NULL);
GenerateDiadic(op_move,0,makereg(1),make_strlab("a0save"));
GenerateDiadic(op_move,0,make_strlab("RunningTCB"),makereg(1));
GenerateDiadic(op_movem,0,make_strlab("d0-d7/a0-a7"),make_strlab("(a0)"));
GenerateDiadic(op_move,0,make_strlab("a0save"),make_strlab("32(a0)"));
GenerateDiadic(op_move,0,make_strlab("usp"),makereg(1));
GenerateDiadic(op_move,0,makereg(1),make_strlab("64(a0)"));
GenerateDiadic(op_move,0,make_strlab("4(a7)"),make_strlab("68(a0)"));
 
//GenerateDiadic(op_move,4,make_string("sr"),make_string("_TCBsrsave"));
//GenerateDiadic(op_movem,4,make_mask(0xFFFF),make_string("_TCBregsave"));
//GenerateDiadic(op_move,4,make_string("usp"),make_string("a0"));
//GenerateDiadic(op_move,4,make_string("a0"),make_string("_TCBuspsave"));
}
 
void gen_regrestore()
{
GenerateDiadic(op_move,0,make_strlab("_TCBuspsave"),make_string("a0"));
GenerateDiadic(op_move,0,make_string("a0"),make_string("usp"));
GenerateDiadic(op_movem,0,make_string("_TCBregsave"),make_mask(0xFFFF));
GenerateDiadic(op_move,0,make_string("_TCBsrsave"),make_string("sr"));
}
*/
/*
void gen_vortex(struct snode *stmt)
{
int lab1;
 
lab1 = nextlabel++;
GenerateDiadic(op_bra,0,make_label(lab1),0);
//gen_ilabel(stmt->label);
gen_regsave();
GenerateStatement(stmt->s1);
gen_regrestore();
GenerateDiadic(op_rte,0,0,0);
GenerateLabel(lab1);
}
*/
 
void GenerateTry(Statement *stmt)
{
int lab1,curlab;
int oldthrow;
char buf[20];
AMODE *ap;
SYM *sym;
 
lab1 = nextlabel++;
oldthrow = throwlab;
throwlab = nextlabel++;
 
GenerateDiadic(op_lea,0,makereg(28),make_label(throwlab));
GenerateStatement(stmt->s1);
GenerateDiadic(op_bra,0,make_label(lab1),NULL);
GenerateLabel(throwlab);
stmt = stmt->s2;
while (stmt) {
throwlab = oldthrow;
curlab = nextlabel++;
GenerateLabel(curlab);
if (stmt->s2==99999)
;
else
GenerateTriadic(op_bnei,0,makereg(2),make_immed((int)stmt->s2),make_label(nextlabel));
// move the throw expression result in 'r1' into the catch variable.
sym = (SYM *)stmt->label;
if (sym) {
switch(sym->tp->size) {
case 1: GenerateDiadic(op_sb,0,makereg(1),make_indexed(sym->value.i,27));
case 2: GenerateDiadic(op_sc,0,makereg(1),make_indexed(sym->value.i,27));
case 4: GenerateDiadic(op_sh,0,makereg(1),make_indexed(sym->value.i,27));
case 8: GenerateDiadic(op_sw,0,makereg(1),make_indexed(sym->value.i,27));
}
}
GenerateStatement(stmt->s1);
stmt=stmt->next;
}
GenerateLabel(lab1);
GenerateDiadic(op_lea,0,makereg(28),make_label(oldthrow));
}
 
void GenerateThrow(Statement *stmt)
{
AMODE *ap;
 
if( stmt != NULL && stmt->exp != NULL )
{
initstack();
ap = GenerateExpression(stmt->exp,F_ALL,8);
if (ap->mode==am_immed)
GenerateTriadic(op_ori,0,makereg(1),makereg(0),ap);
else if( ap->mode != am_reg)
GenerateDiadic(op_lw,0,makereg(1),ap);
else if (ap->preg != 1 )
GenerateTriadic(op_or,0,makereg(1),ap,makereg(0));
ReleaseTempRegister(ap);
GenerateTriadic(op_ori,0,makereg(2),makereg(0),make_immed((int)stmt->label));
}
GenerateDiadic(op_bra,0,make_label(throwlab),NULL);
}
/*
void GenerateCritical(struct snode *stmt)
{
int lab1;
 
lab1 = nextlabel++;
semaphores[lastsph] = stmt->label;
lastsph++;
GenerateLabel(lab1);
GenerateDiadic(op_tas,0,make_string(stmt->label),NULL);
GenerateDiadic(op_bmi,0,make_label(lab1),NULL);
GenerateStatement(stmt->s1);
--lastsph;
semaphores[lastsph] = NULL;
GenerateDiadic(op_move,0,make_immed(0),make_string(stmt->label));
}
*/
 
void GenerateSpinlock(Statement *stmt)
{
int lab1, lab2, lab3, lab4;
AMODE *ap1, *ap2;
 
lab1 = nextlabel++;
ap1 = GetTempRegister();
ap2 = GetTempRegister();
if (stmt->exp) {
lab2 = nextlabel++;
GenerateTriadic(op_ori,0,ap2,makereg(0),make_immed(stmt->exp));
GenerateLabel(lab1);
GenerateTriadic(op_beq,0,ap2,makereg(0),make_label(lab2));
GenerateTriadic(op_subui,0,ap2,ap2,make_immed(1));
GenerateTriadic(op_lwr,0,ap1,make_string(stmt->label),NULL);
GenerateTriadic(op_bne,0,ap1,makereg(0),make_label(lab1),NULL);
GenerateTriadic(op_not,0,ap1,ap1,NULL);
GenerateTriadic(op_swc,0,ap1,make_string(stmt->label),NULL);
GenerateTriadic(op_bnr,0,make_label(lab1),NULL,NULL);
}
else {
GenerateLabel(lab1);
GenerateTriadic(op_lwr,0,ap1,make_string(stmt->label),NULL);
GenerateTriadic(op_bne,0,ap1,makereg(0),make_label(lab1),NULL);
GenerateTriadic(op_not,0,ap1,ap1,NULL);
GenerateTriadic(op_swc,0,ap1,make_string(stmt->label),NULL);
GenerateTriadic(op_bnr,0,make_label(lab1),NULL,NULL);
}
ReleaseTempRegister(ap1);
ReleaseTempRegister(ap2);
GenerateStatement(stmt->s1);
GenerateDiadic(op_sb,0,makereg(0),make_string(stmt->label));
if (stmt->exp) {
lab3 = nextlabel++;
GenerateTriadic(op_bra,0,make_label(lab3),NULL,NULL);
GenerateLabel(lab2);
GenerateStatement(stmt->s2);
GenerateLabel(lab3);
}
else {
printf("Warning: The lockfail code is unreachable because spinlock tries are infinite.\r\n");
}
}
 
void GenerateSpinUnlock(struct snode *stmt)
{
GenerateDiadic(op_sb,0,makereg(0),make_string(stmt->label));
}
/*
* genstmt will generate a statement and follow the next pointer
* until the block is generated.
*/
void GenerateStatement(struct snode *stmt)
{
while( stmt != NULL )
{
switch( stmt->stype )
{
//case st_vortex:
// gen_vortex(stmt);
// break;
case st_try:
GenerateTry(stmt);
break;
case st_throw:
GenerateThrow(stmt);
break;
case st_intoff:
GenerateIntoff(stmt);
break;
case st_stop:
GenerateStop(stmt);
break;
case st_inton:
GenerateInton(stmt);
break;
case st_asm:
GenerateAsm(stmt);
break;
case st_label:
GenerateLabel(stmt->label);
break;
case st_goto:
GenerateDiadic(op_bra,0,make_label(stmt->label),0);
break;
//case st_critical:
// GenerateCritical(stmt);
// break;
case st_spinlock:
GenerateSpinlock(stmt);
break;
case st_spinunlock:
GenerateSpinUnlock(stmt);
break;
case st_expr:
initstack();
GenerateExpression(stmt->exp,F_ALL | F_NOVALUE,
GetNaturalSize(stmt->exp));
break;
case st_return:
GenerateReturn(currentFn,stmt);
break;
case st_if:
GenerateIf(stmt);
break;
case st_do:
GenerateDo(stmt);
break;
case st_dountil:
GenerateDoUntil(stmt);
break;
case st_doloop:
GenerateForever(stmt);
break;
case st_while:
GenerateWhile(stmt);
break;
case st_until:
GenerateUntil(stmt);
break;
case st_for:
GenerateFor(stmt);
break;
case st_forever:
GenerateForever(stmt);
break;
case st_firstcall:
GenerateFirstcall(stmt);
break;
case st_continue:
GenerateDiadic(op_bra,0,make_label(contlab),0);
break;
case st_break:
GenerateDiadic(op_bra,0,make_label(breaklab),0);
break;
case st_switch:
genxswitch(stmt);
break;
default:
printf("DIAG - unknown statement.\n");
break;
}
stmt = stmt->next;
}
}
 
void GenerateIntoff(Statement *stmt)
{
// GenerateDiadic(op_move,0,make_string("sr"),make_string("_TCBsrsave"));
GenerateDiadic(op_sei,0,NULL,NULL);
}
 
void GenerateInton(Statement *stmt)
{
// GenerateDiadic(op_move,0,make_string("_TCBsrsave"),make_string("sr"));
}
 
void GenerateStop(Statement *stmt)
{
GenerateDiadic(op_stop,0,make_immed(0),NULL);
}
 
void GenerateAsm(Statement *stmt)
{
GenerateTriadic(op_asm,0,make_string(stmt->label),NULL,NULL);
}
 
void GenerateFirstcall(Statement *stmt)
{
int lab1, lab2, lab3,lab4,lab5,lab6,lab7;
char buf[20];
AMODE *ap1,*ap2;
 
lab1 = contlab; /* save old continue label */
lab2 = breaklab; /* save old break label */
contlab = nextlabel++; /* new continue label */
lab3 = nextlabel++;
lab4 = nextlabel++;
lab5 = nextlabel++;
lab6 = nextlabel++;
lab7 = nextlabel++;
if( stmt->s1 != NULL ) /* has block */
{
breaklab = nextlabel++;
GenerateLabel(lab3); // marks address of brf
GenerateDiadic(op_bra,0,make_label(lab7),NULL); // branch to the firstcall statement
GenerateLabel(lab6); // prevent optimizer from optimizing move away
GenerateDiadic(op_bra,0,make_label(breaklab),NULL); // then branch around it
GenerateLabel(lab7); // prevent optimizer from optimizing move away
ap1 = GetTempRegister();
ap2 = GetTempRegister();
GenerateDiadic(op_lea,0,ap2,make_label(lab3));
GenerateTriadic(op_andi,0,ap2,ap2,make_immed(0x0c));
GenerateTriadic(op_beqi,0,ap2,make_immed(0x08L),make_label(lab4));
GenerateTriadic(op_beqi,0,ap2,make_immed(0x04L),make_label(lab5));
GenerateDiadic(op_lea,0,ap2,make_label(lab3));
GenerateDiadic(op_lw,0,ap1,make_indirect(ap2->preg));
GenerateTriadic(op_andi,0,ap1,ap1,make_immed(0xFFFFFC0000000000L));
GenerateTriadic(op_ori,0,ap1,ap1,make_immed(0x000037800000000L)); // nop instruction
GenerateDiadic(op_sw,0,ap1,make_indirect(ap2->preg));
GenerateDiadic(op_cache,0,make_string("invil"),make_indirect(ap2->preg));
GenerateDiadic(op_bra,0,make_label(lab6),NULL);
GenerateLabel(lab4);
GenerateDiadic(op_lea,0,ap2,make_label(lab3));
GenerateDiadic(op_lw,0,ap1,make_indirect(ap2->preg));
GenerateTriadic(op_andi,0,ap1,ap1,make_immed(0x00000000000FFFFFL));
GenerateTriadic(op_ori,0,ap1,ap1,make_immed(0x3780000000000000L)); // nop instruction
GenerateDiadic(op_sw,0,ap1,make_indirect(ap2->preg));
GenerateDiadic(op_cache,0,make_string("invil"),make_indirect(ap2->preg));
GenerateDiadic(op_bra,0,make_label(lab6),NULL);
GenerateLabel(lab5);
GenerateDiadic(op_lea,0,ap2,make_label(lab3));
GenerateDiadic(op_lw,0,ap1,make_indexed(4,ap2->preg));
GenerateTriadic(op_andi,0,ap1,ap1,make_immed(0xFFFFFFFFFFF00000L));
GenerateTriadic(op_ori,0,ap1,ap1,make_immed(0x00000000000DE000L)); // nop instruction
GenerateDiadic(op_sw,0,ap1,make_indexed(4,ap2->preg));
GenerateDiadic(op_cache,0,make_string("invil"),make_indexed(4,ap2->preg));
GenerateLabel(lab6);
GenerateStatement(stmt->s1);
GenerateLabel(breaklab);
breaklab = lab2; /* restore old break label */
}
contlab = lab1; /* restore old continue label */
}
/Peepgen.c
0,0 → 1,324
#include <stdio.h>
#include "c.h"
#include "expr.h"
#include "Statement.h"
#include "gen.h"
#include "cglbdec.h"
 
static void AddToPeepList(struct ocode *newc);
void peep_add(struct ocode *ip);
static void PeepoptSub(struct ocode *ip);
void peep_move(struct ocode *ip);
void peep_cmp(struct ocode *ip);
void opt3();
void put_ocode(struct ocode *p);
 
/*
* 68000 C compiler
*
* Copyright 1984, 1985, 1986 Matthew Brandt.
* all commercial rights reserved.
*
* This compiler is intended as an instructive tool for personal use. Any
* use for profit without the written consent of the author is prohibited.
*
* This compiler may be distributed freely for non-commercial use as long
* as this notice stays intact. Please forward any enhancements or questions
* to:
*
* Matthew Brandt
* Box 920337
* Norcross, Ga 30092
*/
/*******************************************************
Copyright 2012 Robert Finch
Modified to support Raptor64 'C64' language
by Robert Finch
robfinch@opencores.org
*******************************************************/
 
struct ocode *peep_head = NULL,
*peep_tail = NULL;
 
AMODE *copy_addr(AMODE *ap)
{
AMODE *newap;
if( ap == NULL )
return NULL;
newap = allocAmode();
memcpy(newap,ap,sizeof(AMODE));
return newap;
}
 
void GenerateMonadic(int op, int len, AMODE *ap1)
{
struct ocode *cd;
cd = (struct ocode *)xalloc(sizeof(struct ocode));
cd->opcode = op;
cd->length = len;
cd->oper1 = copy_addr(ap1);
cd->oper2 = NULL;
cd->oper3 = NULL;
AddToPeepList(cd);
}
 
void GenerateDiadic(int op, int len, AMODE *ap1, AMODE *ap2)
{
struct ocode *cd;
cd = (struct ocode *)xalloc(sizeof(struct ocode));
cd->opcode = op;
cd->length = len;
cd->oper1 = copy_addr(ap1);
cd->oper2 = copy_addr(ap2);
cd->oper3 = NULL;
AddToPeepList(cd);
}
 
void GenerateTriadic(int op, int len, AMODE *ap1, AMODE *ap2, AMODE *ap3)
{
struct ocode *cd;
cd = (struct ocode *)xalloc(sizeof(struct ocode));
cd->opcode = op;
cd->length = len;
cd->oper1 = copy_addr(ap1);
cd->oper2 = copy_addr(ap2);
cd->oper3 = copy_addr(ap3);
AddToPeepList(cd);
}
 
static void AddToPeepList(struct ocode *cd)
{
if( peep_head == NULL )
{
peep_head = peep_tail = cd;
cd->fwd = NULL;
cd->back = NULL;
}
else
{
cd->fwd = NULL;
cd->back = peep_tail;
peep_tail->fwd = cd;
peep_tail = cd;
}
}
 
/*
* add a compiler generated label to the peep list.
*/
void GenerateLabel(int labno)
{
struct ocode *newl;
newl = (struct ocode *)xalloc(sizeof(struct ocode));
newl->opcode = op_label;
newl->oper1 = (struct amode *)labno;
AddToPeepList(newl);
}
 
//void gen_ilabel(char *name)
//{
// struct ocode *new;
// new = (struct ocode *)xalloc(sizeof(struct ocode));
// new->opcode = op_ilabel;
// new->oper1 = (struct amode *)name;
// add_peep(new);
//}
 
/*
* output all code and labels in the peep list.
*/
void flush_peep()
{
if (optimize)
opt3(); /* do the peephole optimizations */
while( peep_head != NULL )
{
if( peep_head->opcode == op_label )
put_label(peep_head->oper1);
else
put_ocode(peep_head);
peep_head = peep_head->fwd;
}
}
 
/*
* output the instruction passed.
*/
void put_ocode(struct ocode *p)
{
put_code(p->opcode,p->length,p->oper1,p->oper2,p->oper3);
}
 
/*
* peephole optimization for move instructions.
* makes quick immediates when possible.
* changes move #0,d to clr d.
* changes long moves to address registers to short when
* possible.
* changes move immediate to stack to pea.
*/
void peep_move(struct ocode *ip)
{
return;
}
 
/*
* compare two address nodes and return true if they are
* equivalent.
*/
int equal_address(AMODE *ap1, AMODE *ap2)
{
if( ap1 == NULL || ap2 == NULL )
return FALSE;
if( ap1->mode != ap2->mode )
return FALSE;
switch( ap1->mode )
{
case am_reg:
return ap1->preg == ap2->preg;
}
return FALSE;
}
 
/*
* peephole optimization for add instructions.
* makes quick immediates out of small constants.
*/
void peep_add(struct ocode *ip)
{
return;
}
 
// 'subui' followed by a 'bne' gets turned into 'loop'
//
static void PeepoptSub(struct ocode *ip)
{
if (ip->opcode==op_subui) {
if (ip->oper3) {
if (ip->oper3->mode==am_immed) {
if (ip->oper3->offset->nodetype==en_icon && ip->oper3->offset->i==1) {
if (ip->fwd) {
if (ip->fwd->opcode==op_bne && ip->fwd->oper2->mode==am_reg && ip->fwd->oper2->preg==0) {
if (ip->fwd->oper1->preg==ip->oper1->preg) {
ip->opcode = op_loop;
ip->oper2 = ip->fwd->oper3;
ip->oper3 = NULL;
if (ip->fwd->back) ip->fwd->back = ip;
ip->fwd = ip->fwd->fwd;
return;
}
}
}
}
}
}
}
return;
}
 
/*
* peephole optimization for compare instructions.
*/
void peep_cmp(struct ocode *ip)
{
return;
}
 
/*
* changes multiplies and divides by convienient values
* to shift operations. op should be either op_asl or
* op_asr (for divide).
*/
void PeepoptMuldiv(struct ocode *ip, int op)
{
int shcnt;
 
if( ip->oper1->mode != am_immed )
return;
if( ip->oper1->offset->nodetype != en_icon )
return;
 
shcnt = ip->oper1->offset->i;
// remove multiply / divide by 1
// This shouldn't get through Optimize, but does sometimes.
if (shcnt==1) {
if (ip->back)
ip->back->fwd = ip->fwd;
if (ip->fwd)
ip->fwd->back = ip->back;
return;
}
/* vax c doesn't do this type of switch well */
if( shcnt == 2) shcnt = 1;
else if( shcnt == 4) shcnt = 2;
else if( shcnt == 8) shcnt = 3;
else if( shcnt == 16) shcnt = 4;
else if( shcnt == 32) shcnt = 5;
else if( shcnt == 64) shcnt = 6;
else if( shcnt == 128) shcnt = 7;
else if( shcnt == 256) shcnt = 8;
else if( shcnt == 512) shcnt = 9;
else if( shcnt == 1024) shcnt = 10;
else if( shcnt == 2048) shcnt = 11;
else if( shcnt == 4096) shcnt = 12;
else if( shcnt == 8192) shcnt = 13;
else if( shcnt == 16384) shcnt = 14;
else if( shcnt == 32768) shcnt = 15;
else return;
ip->oper1->offset->i = shcnt;
ip->opcode = op;
ip->length = 4;
}
 
// Optimize unconditional control flow transfers
// Instructions that follow an unconditional transfer won't be executed
// unless there is a label to branch to them.
//
void PeepoptUctran(struct ocode *ip)
{
if (uctran_off) return;
while( ip->fwd != NULL && ip->fwd->opcode != op_label)
{
ip->fwd = ip->fwd->fwd;
if( ip->fwd != NULL )
ip->fwd->back = ip;
}
}
 
/*
* peephole optimizer. This routine calls the instruction
* specific optimization routines above for each instruction
* in the peep list.
*/
void opt3()
{
struct ocode *ip;
ip = peep_head;
while( ip != NULL )
{
switch( ip->opcode )
{
case op_move:
peep_move(ip);
break;
case op_add:
peep_add(ip);
break;
case op_sub:
PeepoptSub(ip);
break;
case op_cmp:
peep_cmp(ip);
break;
case op_muls:
PeepoptMuldiv(ip,op_shl);
break;
case op_bra:
case op_jmp:
case op_ret:
case op_iret:
PeepoptUctran(ip);
}
ip = ip->fwd;
}
}
/Expr.h
0,0 → 1,68
/*
* 68000 C compiler
*
* Copyright 1984, 1985, 1986 Matthew Brandt.
* all commercial rights reserved.
*
* This compiler is intended as an instructive tool for personal use. Any
* use for profit without the written consent of the author is prohibited.
*
* This compiler may be distributed freely for non-commercial use as long
* as this notice stays intact. Please forward any enhancements or questions
* to:
*
* Matthew Brandt
* Box 920337
* Norcross, Ga 30092
*/
 
/* expression tree descriptions */
 
enum e_node {
en_void, /* used for parameter lists */
en_cbw, en_cbc, en_cbh,
en_ccw, en_cch, en_chw,
en_cwl, en_cld, en_cfd,
en_icon, en_fcon, en_labcon, en_nacon, en_autocon,
en_c_ref, en_uc_ref, en_h_ref, en_uh_ref,
en_b_ref, en_w_ref, en_ub_ref, en_uw_ref,
en_fcall, en_tempref, en_regvar, en_add, en_sub, en_mul, en_mod,
en_div, en_shl, en_shr, en_shru, en_cond, en_assign,
en_asadd, en_assub, en_asmul, en_asdiv, en_asmod, en_asrsh, en_asmulu,
en_aslsh, en_asand, en_asor, en_asxor, en_uminus, en_not, en_compl,
en_eq, en_ne, en_lt, en_le, en_gt, en_ge,
en_and, en_or, en_land, en_lor,
en_xor, en_ainc, en_adec, en_mulu, en_udiv, en_umod, en_ugt,
en_uge, en_ule, en_ult,
en_ref, en_ursh,
en_uwfieldref,en_wfieldref,en_bfieldref,en_ubfieldref,
en_uhfieldref,en_hfieldref,en_ucfieldref,en_cfieldref
};
 
struct enode {
enum e_node nodetype;
enum e_bt etype;
long esize;
__int8 constflag;
__int8 bit_width;
__int8 bit_offset;
// The following could be in a value union
__int64 i;
double f;
char *sp;
struct enode *p[2];
};
 
typedef struct enode ENODE;
 
typedef struct cse {
struct cse *next;
struct enode *exp; /* optimizable expression */
int uses; /* number of uses */
int duses; /* number of dereferenced uses */
short int voidf; /* cannot optimize flag */
short int reg; /* AllocateRegisterVarsd register */
} CSE;
 
 

/Preprocessor.c
0,0 → 1,156
#include <stdio.h>
#include <string.h>
#include "c.h"
#include "expr.h"
#include "Statement.h"
#include "gen.h"
#include "cglbdec.h"
 
/*
* 68000 C compiler
*
* Copyright 1984, 1985, 1986 Matthew Brandt.
* all commercial rights reserved.
*
* This compiler is intended as an instructive tool for personal use. Any
* use for profit without the written consent of the author is prohibited.
*
* This compiler may be distributed freely for non-commercial use as long
* as this notice stays intact. Please forward any enhancements or questions
* to:
*
* Matthew Brandt
* Box 920337
* Norcross, Ga 30092
*/
/*******************************************************
Copyright 2012 Robert Finch
Modified to support Raptor64 'C64' language
by Robert Finch
robfinch@opencores.org
*******************************************************/
 
FILE *inclfile[10];
int incldepth = 0;
int inclline[10];
char *lptr;
extern char inpline[132];
int endifCount = 0;
int dodefine();
int doinclude();
 
int preprocess()
{
++lptr;
lastch = ' ';
NextToken(); /* get first word on line */
if( lastst != id ) {
error(ERR_PREPROC);
return getline(incldepth == 0);
}
if( strcmp(lastid,"include") == 0 )
return doinclude();
else if( strcmp(lastid,"define") == 0 )
return dodefine();
else if (strcmp(lastid,"ifdef")==0)
return doifdef();
else if (strcmp(lastid,"ifndef")==0)
return doifndef();
else if (strcmp(lastid,"endif")==0)
return doendif();
else
{
error(ERR_PREPROC);
return getline(incldepth == 0);
}
}
 
int doinclude()
{
int rv;
NextToken(); /* get file to include */
if( lastst != sconst ) {
error(ERR_INCLFILE);
return getline(incldepth == 0);
}
inclline[incldepth] = lineno;
inclfile[incldepth++] = input; /* push current input file */
input = fopen(laststr,"r");
if( input == 0 ) {
input = inclfile[--incldepth];
error(ERR_CANTOPEN);
rv = getline(incldepth == 0);
}
else {
rv = getline(incldepth == 1);
lineno = -32768; /* dont list include files */
}
return rv;
}
 
int dodefine()
{
SYM *sp;
NextToken(); /* get past #define */
if( lastst != id ) {
error(ERR_DEFINE);
return getline(incldepth == 0);
}
++global_flag; /* always do #define as globals */
sp = allocSYM();
sp->name = litlate(lastid);
sp->value.s = litlate(lptr-1);
insert(sp,&defsyms);
--global_flag;
return getline(incldepth == 0);
}
 
int doifdef()
{
SYM *sp;
int rv;
char *lne;
 
lne = inpline;
NextToken();
if( lastst != id ) {
error(ERR_DEFINE);
return getline(incldepth == 0);
}
endifCount++;
sp = search(lastid,&defsyms);
if (sp == NULL) {
do
rv = getline(incldepth == 0);
while (rv==0 && endifCount!=0);
}
return getline(incldepth == 0);
}
 
int doifndef()
{
SYM *sp;
int rv;
 
NextToken();
if( lastst != id ) {
error(ERR_DEFINE);
return getline(incldepth == 0);
}
endifCount++;
sp = search(lastid,&defsyms);
if (sp != NULL) {
do
rv = getline(incldepth == 0);
while (rv==0 && endifCount!=0);
}
return getline(incldepth == 0);
}
 
int doendif()
{
endifCount--;
return getline(incldepth == 0);
}
 

/C.h
0,0 → 1,159
/*
* 68000 C compiler
*
* Copyright 1984, 1985, 1986 Matthew Brandt.
* all commercial rights reserved.
*
* This compiler is intended as an instructive tool for personal use. Any
* use for profit without the written consent of the author is prohibited.
*
* This compiler may be distributed freely for non-commercial use as long
* as this notice stays intact. Please forward any enhancements or questions
* to:
*
* Matthew Brandt
* Box 920337
* Norcross, Ga 30092
*/
 
/* compiler header file */
 
enum e_sym {
id, cconst, iconst, lconst, sconst, rconst, plus, minus,
star, divide, lshift, rshift, modop, eq, neq, lt, leq, gt,
geq, assign, asplus, asminus, astimes, asdivide, asmodop,
aslshift, asrshift, asand, asor, autoinc, autodec, hook, compl,
comma, colon, semicolon, uparrow, openbr, closebr, begin, end,
openpa, closepa, pointsto, dot, lor, land, not, or, and,
ellipsis,
 
kw_int, kw_byte, kw_icache, kw_dcache,
kw_void, kw_char, kw_float, kw_double, kw_struct, kw_union,
kw_long, kw_short, kw_unsigned, kw_auto, kw_extern,
kw_register, kw_typedef, kw_static, kw_goto, kw_return,
kw_sizeof, kw_break, kw_continue, kw_if, kw_else, kw_elsif,
kw_for, kw_forever, kw_signed,
kw_firstcall, kw_asm, kw_fallthru, kw_until, kw_loop,
kw_try, kw_catch, kw_throw, kw_typenum,
kw_do, kw_while, kw_switch, kw_case, kw_default, kw_enum,
kw_interrupt, kw_vortex, kw_pascal, kw_oscall, kw_nocall, kw_intoff, kw_inton, kw_then,
kw_private,kw_public,kw_stop,kw_critical,kw_spinlock,kw_spinunlock,kw_lockfail,
eof };
 
enum e_sc {
sc_static, sc_auto, sc_global, sc_external, sc_type, sc_const,
sc_member, sc_label, sc_ulabel, sc_typedef };
 
enum e_bt {
bt_byte,
bt_char, bt_short, bt_long, bt_float, bt_double, bt_pointer,
bt_uchar, bt_ushort, bt_ulong,
bt_unsigned, bt_struct, bt_union, bt_enum, bt_void, bt_func, bt_ifunc,
bt_interrupt, bt_oscall, bt_pascal, bt_bitfield, bt_ubitfield, bt_last};
 
struct slit {
struct slit *next;
int label;
char *str;
};
 
struct typ;
 
struct sym {
struct sym *next;
char *name;
__int8 storage_class;
// Function attributes
__int8 NumParms;
struct sym *parms;
struct sym *nextparm;
unsigned int IsPrototype : 1;
unsigned int IsInterrupt : 1;
unsigned int IsNocall : 1;
unsigned int IsPascal : 1;
unsigned int IsLeaf : 1;
unsigned int DoesThrow : 1;
union {
__int64 i;
unsigned __int64 u;
double f;
char *s;
} value;
struct typ *tp;
};
 
typedef struct typ {
__int8 type;
__int16 typeno; // number of the type
unsigned int val_flag : 1; /* is it a value type */
unsigned int isUnsigned : 1;
unsigned int isShort : 1;
unsigned int isVolatile : 1;
__int8 bit_width;
__int8 bit_offset;
long size;
struct stab {
struct sym *head, *tail;
} lst;
struct typ *btp;
char *sname;
} TYP;
 
#define SYM struct sym
//#define TYP struct typ
#define TABLE struct stab
 
#define MAX_STRLEN 120
#define MAX_STLP1 121
#define ERR_SYNTAX 0
#define ERR_ILLCHAR 1
#define ERR_FPCON 2
#define ERR_ILLTYPE 3
#define ERR_UNDEFINED 4
#define ERR_DUPSYM 5
#define ERR_PUNCT 6
#define ERR_IDEXPECT 7
#define ERR_NOINIT 8
#define ERR_INCOMPLETE 9
#define ERR_ILLINIT 10
#define ERR_INITSIZE 11
#define ERR_ILLCLASS 12
#define ERR_BLOCK 13
#define ERR_NOPOINTER 14
#define ERR_NOFUNC 15
#define ERR_NOMEMBER 16
#define ERR_LVALUE 17
#define ERR_DEREF 18
#define ERR_MISMATCH 19
#define ERR_EXPREXPECT 20
#define ERR_WHILEXPECT 21
#define ERR_NOCASE 22
#define ERR_DUPCASE 23
#define ERR_LABEL 24
#define ERR_PREPROC 25
#define ERR_INCLFILE 26
#define ERR_CANTOPEN 27
#define ERR_DEFINE 28
#define ERR_CATCHEXPECT 29
#define ERR_BITFIELD_WIDTH 30
#define ERR_EXPRTOOCOMPLEX 31
#define ERR_ASMTOOLONG 32
#define ERR_TOOMANYCASECONSTANTS 33
#define ERR_CATCHSTRUCT 34
 
/* alignment sizes */
 
#define AL_BYTE 1
#define AL_CHAR 2
#define AL_SHORT 4
#define AL_LONG 8
#define AL_POINTER 8
#define AL_FLOAT 4
#define AL_DOUBLE 8
#define AL_STRUCT 8
 
#define TRUE 1
#define FALSE 0
#define NULL ((void *)0)
 

/err.c
0,0 → 1,84
// ============================================================================
// (C) 2012 Robert Finch
// All Rights Reserved.
// robfinch<remove>@opencores.org
//
// C64 - Raptor64 'C' derived language compiler
// - 64 bit CPU
//
// This source file is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file 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 this program. If not, see <http://www.gnu.org/licenses/>.
//
// ============================================================================
//
#include "c.h"
 
extern int numerrs;
extern int total_errors;
extern int errno[80];
 
static char *errtextstr[] = {
"Syntax error",
"Illegal character",
"Floating point",
"Illegal type",
"Undefined symbol",
"Bad punctuation",
"Identifier expected",
"No initializer",
"Incomplete statement",
"Illegal initializer",
"Illegal class",
"block",
"No pointer",
"No function",
"No member",
"LValue required",
"Dereference",
"Mismatch",
"Expression expected",
"While/Until expected",
"Missing case statement",
"Duplicate case statement",
"Bad label",
"Preprocessor error",
"Include file",
"Can't open",
"Define",
"Expecting a catch statement",
"Bad bitfield width",
"Expression too complex",
"Asm statement too long - break into multiple statements",
"Too many case constants",
"Attempting to catch a structure - aggregates may not be caught - use a pointer to struct"
};
 
char *errtext(int errnum)
{
return errtextstr[errnum];
}
 
/*
* error - print error information
*/
void error(int n)
{
if (numerrs < 80) {
errno[numerrs++] = n;
++total_errors;
}
else
exit(1);
}
 
 
/Intexpr.c
0,0 → 1,60
#include <stdio.h>
#include "c.h"
#include "expr.h"
#include "gen.h"
#include "cglbdec.h"
 
/*
* 68000 C compiler
*
* Copyright 1984, 1985, 1986 Matthew Brandt.
* all commercial rights reserved.
*
* This compiler is intended as an instructive tool for personal use. Any
* use for profit without the written consent of the author is prohibited.
*
* This compiler may be distributed freely for non-commercial use as long
* as this notice stays intact. Please forward any enhancements or questions
* to:
*
* Matthew Brandt
* Box 920337
* Norcross, Ga 30092
*/
 
/*******************************************************
Modified to support Raptor64 'C64' language
by Robert Finch
robfinch@opencores.org
*******************************************************/
 
int GetIntegerExpression() /* simple integer value */
{
int temp;
SYM *sp;
 
if(lastst == id) {
sp = gsearch(lastid);
if(sp == NULL) {
error(ERR_UNDEFINED);
NextToken();
return 0;
}
if(sp->storage_class != sc_const) {
error(ERR_SYNTAX);
NextToken();
return 0;
}
NextToken();
return sp->value.i;
}
else if(lastst == iconst)
{
temp = ival;
NextToken();
return temp;
}
NextToken();
error(ERR_SYNTAX);
return 0;
}
/Optimize.c
0,0 → 1,420
#include <stdio.h>
#include "c.h"
#include "expr.h"
#include "gen.h"
#include "cglbdec.h"
 
/*
* 68000 C compiler
*
* Copyright 1984, 1985, 1986 Matthew Brandt.
* all commercial rights reserved.
*
* This compiler is intended as an instructive tool for personal use. Any
* use for profit without the written consent of the author is prohibited.
*
* This compiler may be distributed freely for non-commercial use as long
* as this notice stays intact. Please forward any enhancements or questions
* to:
*
* Matthew Brandt
* Box 920337
* Norcross, Ga 30092
*/
 
/* Modified to support 64 bit Raptor64 by
Robert Finch robfinch<remove>@opencores.org
*/
 
void fold_const(struct enode **node);
 
/*
* dooper will execute a constant operation in a node and
* modify the node to be the result of the operation.
*/
void dooper(ENODE **node)
{
ENODE *ep;
 
ep = *node;
switch( ep->nodetype ) {
case en_add:
ep->nodetype = en_icon;
ep->i = ep->p[0]->i + ep->p[1]->i;
break;
case en_sub:
ep->nodetype = en_icon;
ep->i = ep->p[0]->i - ep->p[1]->i;
break;
case en_mul:
case en_mulu:
ep->nodetype = en_icon;
ep->i = ep->p[0]->i * ep->p[1]->i;
break;
case en_div:
case en_udiv:
ep->nodetype = en_icon;
ep->i = ep->p[0]->i / ep->p[1]->i;
break;
case en_shl:
ep->nodetype = en_icon;
ep->i = ep->p[0]->i << ep->p[1]->i;
break;
case en_shr:
ep->nodetype = en_icon;
ep->i = ep->p[0]->i >> ep->p[1]->i;
break;
case en_shru:
ep->nodetype = en_icon;
ep->i = (unsigned)ep->p[0]->i >> ep->p[1]->i;
break;
case en_and:
ep->nodetype = en_icon;
ep->i = ep->p[0]->i & ep->p[1]->i;
break;
case en_or:
ep->nodetype = en_icon;
ep->i = ep->p[0]->i | ep->p[1]->i;
break;
case en_xor:
ep->nodetype = en_icon;
ep->i = ep->p[0]->i ^ ep->p[1]->i;
break;
}
}
 
/*
* return which power of two i is or -1.
*/
int pwrof2(__int64 i)
{
int p;
__int64 q;
 
q = 2;
p = 1;
while( q > 0 )
{
if( q == i )
return p;
q <<= 1;
++p;
}
return -1;
}
 
/*
* make a mod mask for a power of two.
*/
__int64 mod_mask(int i)
{
__int64 m;
m = 0;
while( i-- )
m = (m << 1) | 1;
return m;
}
 
/*
* opt0 - delete useless expressions and combine constants.
*
* opt0 will delete expressions such as x + 0, x - 0, x * 0,
* x * 1, 0 / x, x / 1, x mod 0, etc from the tree pointed to
* by node and combine obvious constant operations. It cannot
* combine name and label constants but will combine icon type
* nodes.
*/
void opt0(ENODE **node)
{
ENODE *ep;
__int64 val, sc;
 
ep = *node;
if( ep == NULL )
return;
switch( (*node)->nodetype ) {
case en_b_ref:
case en_c_ref:
case en_h_ref:
case en_w_ref: /* optimize unary node */
case en_ub_ref:
case en_uc_ref:
case en_uh_ref:
case en_uw_ref: /* optimize unary node */
case en_cbc:
case en_cbh:
case en_cbw:
case en_cch:
case en_ccw:
case en_chw:
case en_ainc:
case en_adec:
case en_not:
case en_compl:
opt0( &((*node)->p[0]));
return;
case en_uminus:
opt0( &(ep->p[0]));
if( ep->p[0]->nodetype == en_icon )
{
ep->nodetype = en_icon;
ep->i = -ep->p[0]->i;
}
return;
case en_add:
case en_sub:
opt0(&(ep->p[0]));
opt0(&(ep->p[1]));
if( ep->p[0]->nodetype == en_icon ) {
if( ep->p[1]->nodetype == en_icon ) {
dooper(node);
return;
}
if( ep->p[0]->i == 0 ) {
if( ep->nodetype == en_sub )
{
ep->p[0] = ep->p[1];
ep->nodetype = en_uminus;
}
else
*node = ep->p[1];
return;
}
}
else if( ep->p[1]->nodetype == en_icon ) {
if( ep->p[1]->i == 0 ) {
*node = ep->p[0];
return;
}
}
return;
case en_mul:
case en_mulu:
opt0(&(ep->p[0]));
opt0(&(ep->p[1]));
if( ep->p[0]->nodetype == en_icon ) {
if( ep->p[1]->nodetype == en_icon ) {
dooper(node);
return;
}
val = ep->p[0]->i;
if( val == 0 ) {
*node = ep->p[0];
return;
}
if( val == 1 ) {
*node = ep->p[1];
return;
}
sc = pwrof2(val);
if( sc != -1 )
{
swap_nodes(ep);
ep->p[1]->i = sc;
ep->nodetype = en_shl;
}
}
else if( ep->p[1]->nodetype == en_icon ) {
val = ep->p[1]->i;
if( val == 0 ) {
*node = ep->p[1];
return;
}
if( val == 1 ) {
*node = ep->p[0];
return;
}
sc = pwrof2(val);
if( sc != -1 )
{
ep->p[1]->i = sc;
ep->nodetype = en_shl;
}
}
break;
case en_div:
case en_udiv:
opt0(&(ep->p[0]));
opt0(&(ep->p[1]));
if( ep->p[0]->nodetype == en_icon ) {
if( ep->p[1]->nodetype == en_icon ) {
dooper(node);
return;
}
if( ep->p[0]->i == 0 ) { /* 0/x */
*node = ep->p[0];
return;
}
}
else if( ep->p[1]->nodetype == en_icon ) {
val = ep->p[1]->i;
if( val == 1 ) { /* x/1 */
*node = ep->p[0];
return;
}
sc = pwrof2(val);
if( sc != -1 )
{
ep->p[1]->i = sc;
ep->nodetype = en_shr;
}
}
break;
case en_mod:
opt0(&(ep->p[0]));
opt0(&(ep->p[1]));
if( ep->p[1]->nodetype == en_icon )
{
if( ep->p[0]->nodetype == en_icon )
{
dooper(node);
return;
}
sc = pwrof2(ep->p[1]->i);
if( sc != -1 )
{
ep->p[1]->i = mod_mask(sc);
ep->nodetype = en_and;
}
}
break;
case en_and: case en_or:
case en_xor: case en_shr: case en_shru:
case en_shl:
opt0(&(ep->p[0]));
opt0(&(ep->p[1]));
if( ep->p[0]->nodetype == en_icon &&
ep->p[1]->nodetype == en_icon )
dooper(node);
break;
case en_land: case en_lor:
case en_ult: case en_ule:
case en_ugt: case en_uge:
case en_lt: case en_le:
case en_gt: case en_ge:
case en_eq: case en_ne:
case en_asand: case en_asor:
case en_asadd: case en_assub:
case en_asmul: case en_asdiv:
case en_asmod: case en_asrsh:
case en_aslsh: case en_cond:
case en_fcall: case en_void:
case en_assign:
opt0(&(ep->p[0]));
opt0(&(ep->p[1]));
break;
}
}
 
/*
* xfold will remove constant nodes and return the values to
* the calling routines.
*/
__int64 xfold(ENODE *node)
{
__int64 i;
 
if( node == NULL )
return 0;
switch( node->nodetype )
{
case en_icon:
i = node->i;
node->i = 0;
return i;
case en_add:
return xfold(node->p[0]) + xfold(node->p[1]);
case en_sub:
return xfold(node->p[0]) - xfold(node->p[1]);
case en_mul:
case en_mulu:
if( node->p[0]->nodetype == en_icon )
return xfold(node->p[1]) * node->p[0]->i;
else if( node->p[1]->nodetype == en_icon )
return xfold(node->p[0]) * node->p[1]->i;
else return 0;
case en_shl:
if( node->p[0]->nodetype == en_icon )
return xfold(node->p[1]) << node->p[0]->i;
else if( node->p[1]->nodetype == en_icon )
return xfold(node->p[0]) << node->p[1]->i;
else return 0;
case en_uminus:
return - xfold(node->p[0]);
case en_shr: case en_div: case en_udiv: case en_shru:
case en_mod: case en_asadd:
case en_assub: case en_asmul:
case en_asdiv: case en_asmod:
case en_and: case en_land:
case en_or: case en_lor:
case en_xor: case en_asand:
case en_asor: case en_void:
case en_fcall: case en_assign:
fold_const(&node->p[0]);
fold_const(&node->p[1]);
return 0;
case en_ub_ref: case en_uw_ref:
case en_uc_ref: case en_uh_ref:
case en_b_ref: case en_w_ref:
case en_c_ref: case en_h_ref:
case en_compl:
case en_not:
fold_const(&node->p[0]);
return 0;
}
return 0;
}
 
/*
* reorganize an expression for optimal constant grouping.
*/
void fold_const(ENODE **node)
{ ENODE *ep;
__int64 i;
ep = *node;
if( ep == 0 )
return;
if( ep->nodetype == en_add )
{
if( ep->p[0]->nodetype == en_icon )
{
ep->p[0]->i += xfold(ep->p[1]);
return;
}
else if( ep->p[1]->nodetype == en_icon )
{
ep->p[1]->i += xfold(ep->p[0]);
return;
}
}
else if( ep->nodetype == en_sub )
{
if( ep->p[0]->nodetype == en_icon )
{
ep->p[0]->i -= xfold(ep->p[1]);
return;
}
else if( ep->p[1]->nodetype == en_icon )
{
ep->p[1]->i -= xfold(ep->p[0]);
return;
}
}
i = xfold(ep);
if( i != 0 )
{
ep = makeinode(en_icon,i);
ep = makenode(en_add,ep,*node);
*node = ep;
}
}
 
/*
* apply all constant optimizations.
*/
void opt4(struct enode **node)
{
opt0(node);
fold_const(node);
opt0(node);
}
/Outcode.c
0,0 → 1,477
#include <stdio.h>
#include <string.h>
#include "c.h"
#include "expr.h"
#include "gen.h"
#include "cglbdec.h"
 
/*
* 68000 C compiler
*
* Copyright 1984, 1985, 1986 Matthew Brandt.
* all commercial rights reserved.
*
* This compiler is intended as an instructive tool for personal use. Any
* use for profit without the written consent of the author is prohibited.
*
* This compiler may be distributed freely for non-commercial use as long
* as this notice stays intact. Please forward any enhancements or questions
* to:
*
* Matthew Brandt
* Box 920337
* Norcross, Ga 30092
*/
 
/*******************************************************
Modified to support Raptor64 'C64' language
by Robert Finch
robfinch@opencores.org
*******************************************************/
 
void put_mask(int mask);
void align(int n);
 
/* variable initialization */
 
enum e_gt { nogen, bytegen, chargen, halfgen, wordgen, longgen };
enum e_sg { noseg, codeseg, dataseg };
 
int gentype = nogen;
int curseg = noseg;
int outcol = 0;
 
struct oplst {
char *s;
int ov;
} opl[] =
{ {"move",op_move}, {"add",op_add}, {"addu", op_addu}, {"mov", op_mov},
{"add",op_addi}, {"sub",op_sub}, {"subu", op_subu},
{"subi",op_subi}, {"and",op_and},
{"sext8",op_sext8}, {"sext16", op_sext16}, {"sext32", op_sext32},
{"subui",op_subui}, {"shru", op_shru}, {"divsi", op_divsi}, {"not", op_not},
{"addui",op_addui}, {"shr", op_shr}, {"dw", op_dw}, {"shl", op_shl}, {"shr", op_shr}, {"shru", op_shru},
{"shli", op_shli}, {"shri", op_shri}, {"shrui", op_shrui},
{"sw", op_sw}, {"lw", op_lw}, {"lh", op_lh}, {"lc", op_lc}, {"lb", op_lb},
{"lm", op_lm}, {"sm",op_sm}, {"sb",op_sb}, {"sc",op_sc}, {"sh",op_sh},
{"call", op_call}, {"ret", op_ret}, {"loop", op_loop}, {"beqi", op_beqi},
{"jal", op_jal}, {"lwr", op_lwr}, {"swc", op_swc}, {"cache",op_cache},
{"or",op_or}, {"ori",op_ori}, {"iret", op_iret}, {"andi", op_andi},
{"xor",op_xor}, {"xori", op_xori}, {"muls",op_muls}, {"mulsi", op_mulsi}, {"mului", op_mului},
{"divs",op_divs}, {"swap",op_swap}, {"mod", op_mod}, {"modu", op_modu},
{"beq",op_beq}, {"bnei", op_bnei}, {"sei", op_sei},
{"bltu", op_bltu}, {"bleu",op_bleu}, {"bgtu",op_bgtu}, {"bgeu", op_bgeu},
{"bhi",op_bhi}, {"bhs",op_bhs}, {"blo",op_blo},
{"bls",op_bls}, {"mulu",op_mulu}, {"divu",op_divu},
{"bne",op_bne}, {"blt",op_blt}, {"ble",op_ble},
{"bgt",op_bgt}, {"bge",op_bge}, {"neg",op_neg}, {"bnr", op_bnr},
{"not",op_not}, {"cmp",op_cmp}, {"ext",op_ext},
{"jmp",op_jmp},
{"lea",op_lea}, {"asr",op_asr},
{"clr",op_clr}, {"link",op_link}, {"unlk",op_unlk},
{"bra",op_bra}, {"pea",op_pea},
{"cmp",op_cmpi}, {"tst",op_tst},
{"stop", op_stop},
{"bmi", op_bmi},
{"dc",op_dc},
{"",op_empty}, {"",op_asm},
{0,0} };
 
static char *pad(char *op)
{
static char buf[20];
int n;
 
n = strlen(op);
strncpy(buf,op,20);
if (n < 5) {
strcat(buf, " ");
buf[5] = '\0';
}
return buf;
}
 
void putop(int op)
{
int i;
i = 0;
while( opl[i].s )
{
if( opl[i].ov == op )
{
fprintf(output,"\t%s",pad(opl[i].s));
return;
}
++i;
}
printf("DIAG - illegal opcode.\n");
}
 
static void PutConstant(ENODE *offset)
{
switch( offset->nodetype )
{
case en_autocon:
case en_icon:
fprintf(output,"%I64d",offset->i);
break;
case en_labcon:
fprintf(output,"L_%I64d",offset->i);
break;
case en_nacon:
fprintf(output,"%s",offset->sp);
break;
case en_add:
PutConstant(offset->p[0]);
fprintf(output,"+");
PutConstant(offset->p[1]);
break;
case en_sub:
PutConstant(offset->p[0]);
fprintf(output,"-");
PutConstant(offset->p[1]);
break;
case en_uminus:
fprintf(output,"-");
PutConstant(offset->p[0]);
break;
default:
printf("DIAG - illegal constant node.\n");
break;
}
}
 
char *RegMoniker(int regno)
{
static char buf[4][20];
static int n;
 
n = (n + 1) & 3;
switch(regno) {
case 27: sprintf(&buf[n], "bp"); break;
case 28: sprintf(&buf[n], "xlr"); break;
case 29: sprintf(&buf[n], "pc"); break;
case 30: sprintf(&buf[n], "sp"); break;
case 31: sprintf(&buf[n], "lr"); break;
default: sprintf(&buf[n], "r%d", regno); break;
}
return &buf[n];
}
 
void PutAddressMode(AMODE *ap)
{
switch( ap->mode )
{
case am_immed:
fprintf(output,"#");
case am_direct:
PutConstant(ap->offset);
break;
case am_reg:
fprintf(output, "%s", RegMoniker(ap->preg));
break;
case am_ind:
//if (ap->offset != NULL) {
// if (ap->offset->i != 0)
// fprintf(output, "%I64d[r%d]", ap->offset->i, ap->preg);
// else
// fprintf(output,"[r%d]",ap->preg);
//}
//else
fprintf(output,"[%s]",RegMoniker(ap->preg));
break;
case am_ainc:
fprintf(output,"******[r%d]",ap->preg);
fprintf(output,"addui\ta%d,a%d,#",ap->preg,ap->preg);
break;
case am_adec:
fprintf(output,"subui\ta%d,a%d,#",ap->preg,ap->preg);
fprintf(output,"******[a%d]",ap->preg);
break;
case am_indx:
PutConstant(ap->offset);
fprintf(output,"[%s]",RegMoniker(ap->preg));
break;
case am_indx2:
PutConstant(ap->offset);
fprintf(output,"[%s+%s]",RegMoniker(ap->preg),RegMoniker(ap->sreg));
break;
case am_indx3:
PutConstant(ap->offset);
fprintf(output,"[%s+%s]",RegMoniker(ap->preg),RegMoniker(ap->sreg));
break;
case am_mask:
put_mask(ap->offset);
break;
default:
printf("DIAG - illegal address mode.\n");
break;
}
}
 
/*
* output a generic instruction.
*/
void put_code(int op, int len,AMODE *aps,AMODE *apd,AMODE *ap3)
{ if( op == op_dc )
{
switch( len )
{
case 1: fprintf(output,"\tdb"); break;
case 2: fprintf(output,"\tdc"); break;
case 4: fprintf(output,"\tdh"); break;
case 8: fprintf(output,"\tdw"); break;
}
}
else
{
putop(op);
}
if( aps != 0 )
{
fprintf(output,"\t");
PutAddressMode(aps);
if( apd != 0 )
{
fprintf(output,",");
PutAddressMode(apd);
if (ap3 != NULL) {
fprintf(output,",");
PutAddressMode(ap3);
}
}
}
fprintf(output,"\n");
}
 
/*
* generate a register mask for restore and save.
*/
void put_mask(int mask)
{
int nn;
int first = 1;
 
for (nn = 0; nn < 32; nn++) {
if (mask & (1<<nn)) {
if (!first)
fprintf(output,"/");
fprintf(output,"r%d",nn);
first = 0;
}
}
// fprintf(output,"#0x%04x",mask);
 
}
 
/*
* generate a register name from a tempref number.
*/
void putreg(int r)
{
fprintf(output, "r%d", r);
}
 
/*
* generate a named label.
*/
void gen_strlab(char *s)
{ fprintf(output,"%s:\n",s);
}
 
/*
* output a compiler generated label.
*/
void put_label(int lab)
{
fprintf(output,"L_%d:\n",lab);
}
 
void GenerateByte(int val)
{
if( gentype == bytegen && outcol < 60) {
fprintf(output,",%d",val & 0x00ff);
outcol += 4;
}
else {
nl();
fprintf(output,"\tdb\t%d",val & 0x00ff);
gentype = bytegen;
outcol = 19;
}
}
 
void GenerateChar(int val)
{
if( gentype == chargen && outcol < 60) {
fprintf(output,",%d",val & 0xffff);
outcol += 6;
}
else {
nl();
fprintf(output,"\tdc\t%d",val & 0xffff);
gentype = chargen;
outcol = 21;
}
}
 
void genhalf(int val)
{
if( gentype == bytegen && outcol < 60) {
fprintf(output,",%d",val & 0xffffffff);
outcol += 10;
}
else {
nl();
fprintf(output,"\tdh\t%d",val & 0xffffffff);
gentype = halfgen;
outcol = 25;
}
}
 
void GenerateWord(__int64 val)
{
if( gentype == wordgen && outcol < 58) {
fprintf(output,",%I64d",val);
outcol += 18;
}
else {
nl();
fprintf(output,"\tdw\t%I64d",val);
gentype = wordgen;
outcol = 33;
}
}
 
void GenerateLong(__int64 val)
{ if( gentype == longgen && outcol < 56) {
fprintf(output,",%I64d",val);
outcol += 10;
}
else {
nl();
fprintf(output,"\tdw\t%I64d",val);
gentype = longgen;
outcol = 25;
}
}
 
void GenerateReference(SYM *sp,int offset)
{
char sign;
if( offset < 0) {
sign = '-';
offset = -offset;
}
else
sign = '+';
if( gentype == longgen && outcol < 55 - strlen(sp->name)) {
if( sp->storage_class == sc_static)
fprintf(output,",L_%I64d%c%d",sp->value.i,sign,offset);
else
fprintf(output,",%s%c%d",sp->name,sign,offset);
outcol += (11 + strlen(sp->name));
}
else {
nl();
if(sp->storage_class == sc_static)
fprintf(output,"\tdw\tL_%I64d%c%d",sp->value.i,sign,offset);
else
fprintf(output,"\tdw\t%s%c%d",sp->name,sign,offset);
outcol = 26 + strlen(sp->name);
gentype = longgen;
}
}
 
void genstorage(int nbytes)
{ nl();
fprintf(output,"\tdcb.b\t%d,0xff\n",nbytes);
}
 
void GenerateLabelReference(int n)
{ if( gentype == longgen && outcol < 58) {
fprintf(output,",L_%d",n);
outcol += 6;
}
else {
nl();
fprintf(output,"\tlong\tL_%d",n);
outcol = 22;
gentype = longgen;
}
}
 
/*
* make s a string literal and return it's label number.
*/
int stringlit(char *s)
{
struct slit *lp;
 
++global_flag; /* always AllocateRegisterVars from global space. */
lp = (struct slit *)xalloc(sizeof(struct slit));
lp->label = nextlabel++;
lp->str = litlate(s);
lp->next = strtab;
strtab = lp;
--global_flag;
return lp->label;
}
 
/*
* dump the string literal pool.
*/
void dumplits()
{
char *cp;
 
cseg();
nl();
align(8);
nl();
while( strtab != NULL) {
nl();
put_label(strtab->label);
cp = strtab->str;
while(*cp)
GenerateChar(*cp++);
GenerateChar(0);
strtab = strtab->next;
}
nl();
}
 
void nl()
{ if(outcol > 0) {
fprintf(output,"\n");
outcol = 0;
gentype = nogen;
}
}
 
void align(int n)
{
fprintf(output,"\talign\t%d\n",n);
}
 
void cseg()
{
if( curseg != codeseg) {
nl();
fprintf(output,"\tcode\n");
fprintf(output,"\talign\t16\n");
curseg = codeseg;
}
}
 
void dseg()
{
if( curseg != dataseg) {
nl();
fprintf(output,"\tdata\n");
fprintf(output,"\talign\t8\n");
curseg = dataseg;
}
}
 

/ParseDeclarations.c
0,0 → 1,647
#include <stdio.h>
#include <string.h>
#include "c.h"
#include "expr.h"
#include "Statement.h"
#include "gen.h"
#include "cglbdec.h"
 
/*
* 68000 C compiler
*
* Copyright 1984, 1985, 1986 Matthew Brandt.
* all commercial rights reserved.
*
* This compiler is intended as an instructive tool for personal use. Any
* use for profit without the written consent of the author is prohibited.
*
* This compiler may be distributed freely for non-commercial use as long
* as this notice stays intact. Please forward any enhancements or questions
* to:
*
* Matthew Brandt
* Box 920337
* Norcross, Ga 30092
*/
/*******************************************************
Modified to support Raptor64 'C64' language
by Robert Finch
robfinch@opencores.org
*******************************************************/
 
TYP *head = NULL;
TYP *tail = NULL;
char *declid = NULL;
TABLE tagtable = {0,0};
TYP stdconst = { bt_long, bt_long, 1, FALSE, FALSE, FALSE, 0, 0, 8, {0, 0}, 0, "stdconst"};
char *names[20];
int nparms = 0;
int funcdecl = FALSE;
int catchdecl = FALSE;
int isTypedef = FALSE;
int isUnion = FALSE;
int isUnsigned = FALSE;
 
/* variable for bit fields */
static int bit_max; // largest bitnumber
int bit_offset; /* the actual offset */
int bit_width; /* the actual width */
int bit_next; /* offset for next variable */
 
int declbegin(int st);
void dodecl(int defclass);
void ParseDeclarationSuffix();
void declstruct(int ztype);
void structbody(TYP *tp, int ztype);
void ParseEnumDeclaration(TABLE *table);
void enumbody(TABLE *table);
 
int imax(int i, int j)
{ return (i > j) ? i : j;
}
 
 
char *litlate(char *s)
{
char *p;
p = xalloc(strlen(s) + 1);
strcpy(p,s);
return p;
}
 
TYP *maketype(int bt, int siz)
{
TYP *tp;
tp = allocTYP();
tp->val_flag = 0;
tp->size = siz;
tp->type = bt;
tp->typeno = bt;
tp->sname = 0;
tp->lst.head = 0;
return tp;
}
 
void ParseSpecifier(TABLE *table)
{
SYM *sp;
 
isUnsigned = FALSE;
for (;;) {
switch (lastst) {
case kw_signed: // Ignore 'signed'
NextToken();
break;
case kw_typedef:
isTypedef = TRUE;
NextToken();
break;
case kw_nocall:
isNocall = TRUE;
head = tail = maketype(bt_oscall,8);
NextToken();
goto lxit;
case kw_oscall:
isOscall = TRUE;
head = tail = maketype(bt_oscall,8);
NextToken();
goto lxit;
case kw_interrupt:
isInterrupt = TRUE;
head = tail = maketype(bt_interrupt,8);
NextToken();
goto lxit;
case kw_pascal:
isPascal = TRUE;
head = tail = maketype(bt_pascal,8);
NextToken();
break;
case kw_byte:
head = tail = maketype(bt_byte,1);
NextToken();
head->isUnsigned = isUnsigned;
bit_max = 8;
goto lxit;
case kw_char:
head = tail = maketype(bt_char,2);
NextToken();
head->isUnsigned = isUnsigned;
bit_max = 16;
goto lxit;
case kw_short:
head = tail = maketype(bt_short,4);
bit_max = 32;
NextToken();
if( lastst == kw_int )
NextToken();
head->isUnsigned = isUnsigned;
head->isShort = TRUE;
goto lxit;
break;
case kw_long: // long, long int
if (lastst==kw_int) {
NextToken();
}
if (lastst==kw_float)
head = tail = maketype(bt_double,8);
else
head = tail = maketype(bt_long,8);
NextToken();
if (lastst==kw_oscall) {
isOscall = TRUE;
NextToken();
}
if (lastst==kw_nocall) {
isNocall = TRUE;
NextToken();
}
head->isUnsigned = isUnsigned;
bit_max = 64;
goto lxit;
break;
case kw_int:
head = tail = maketype(bt_long,8);
head->isUnsigned = isUnsigned;
NextToken();
if (lastst==kw_oscall) {
isOscall = TRUE;
NextToken();
}
if (lastst==kw_nocall) {
isNocall = TRUE;
NextToken();
}
bit_max = 64;
goto lxit;
break;
case kw_unsigned:
NextToken();
isUnsigned = TRUE;
break;
case id: /* no type ParseSpecifierarator */
sp = search(lastid,&gsyms[0]);
if (sp) {
if (sp->storage_class==sc_typedef) {
NextToken();
head = tail = sp->tp;
}
else
head = tail = sp->tp;
// head = tail = maketype(bt_long,4);
}
else {
head = tail = maketype(bt_long,8);
bit_max = 64;
}
goto lxit;
break;
case kw_float:
head = tail = maketype(bt_float,4);
NextToken();
bit_max = 32;
goto lxit;
case kw_double:
head = tail = maketype(bt_double,8);
NextToken();
bit_max = 64;
goto lxit;
case kw_void:
head = tail = maketype(bt_void,0);
NextToken();
if (lastst==kw_interrupt) {
isInterrupt = TRUE;
NextToken();
}
if (lastst==kw_nocall) {
isNocall = TRUE;
NextToken();
}
bit_max = 0;
goto lxit;
case kw_enum:
NextToken();
ParseEnumDeclaration(table);
bit_max = 16;
goto lxit;
case kw_struct:
NextToken();
ParseStructDeclaration(bt_struct);
goto lxit;
case kw_union:
NextToken();
ParseStructDeclaration(bt_union);
goto lxit;
default:
goto lxit;
}
}
lxit:;
}
 
void ParseDeclarationPrefix(char isUnion)
{
TYP *temp1, *temp2, *temp3, *temp4;
switch (lastst) {
case id:
declid = litlate(lastid);
if (funcdecl==1)
names[nparms++] = declid;
NextToken();
if (lastst == colon) {
NextToken();
bit_width = GetIntegerExpression();
if (isUnion)
bit_offset = 0;
else
bit_offset = bit_next;
if (bit_width < 0 || bit_width > bit_max) {
error(ERR_BITFIELD_WIDTH);
bit_width = 1;
}
if (bit_width == 0 || bit_offset + bit_width > bit_max)
bit_offset = 0;
bit_next = bit_offset + bit_width;
break; // no ParseDeclarationSuffix()
}
ParseDeclarationSuffix();
break;
case star:
temp1 = maketype(bt_pointer,8);
temp1->btp = head;
head = temp1;
if(tail == NULL)
tail = head;
NextToken();
ParseDeclarationPrefix(isUnion);
break;
case openpa:
NextToken();
temp1 = head;
temp2 = tail;
head = tail = NULL;
ParseDeclarationPrefix(isUnion);
needpunc(closepa);
temp3 = head;
temp4 = tail;
head = temp1;
tail = temp2;
ParseDeclarationSuffix();
temp4->btp = head;
if(temp4->type == bt_pointer && temp4->val_flag != 0 && head != NULL)
temp4->size *= head->size;
head = temp3;
break;
default:
ParseDeclarationSuffix();
break;
}
}
 
// Take care of the () or [] trailing part of a ParseSpecifieraration
//
void ParseDeclarationSuffix()
{
TYP *temp1;
switch (lastst) {
case openbr:
NextToken();
temp1 = maketype(bt_pointer,0);
temp1->val_flag = 1;
temp1->btp = head;
if(lastst == closebr) {
temp1->size = 0;
NextToken();
}
else if(head != NULL) {
temp1->size = GetIntegerExpression() * head->size;
needpunc(closebr);
}
else {
temp1->size = GetIntegerExpression();
needpunc(closebr);
}
head = temp1;
if( tail == NULL)
tail = head;
ParseDeclarationSuffix();
break;
case openpa:
NextToken();
temp1 = maketype(bt_func,0);
temp1->val_flag = 1;
temp1->btp = head;
head = temp1;
if( lastst == closepa) {
NextToken();
if(lastst == begin)
temp1->type = bt_ifunc;
}
else
temp1->type = bt_ifunc;
break;
}
}
 
int alignment(TYP *tp)
{
switch(tp->type) {
case bt_byte: return AL_BYTE;
case bt_char: return AL_CHAR;
case bt_short: return AL_SHORT;
case bt_long: return AL_LONG;
case bt_enum: return AL_CHAR;
case bt_pointer:
if(tp->val_flag)
return alignment(tp->btp);
else
return AL_POINTER;
case bt_float: return AL_FLOAT;
case bt_double: return AL_DOUBLE;
case bt_struct:
case bt_union: return AL_STRUCT;
default: return AL_CHAR;
}
}
 
/*
* process ParseSpecifierarations of the form:
*
* <type> <ParseSpecifier>, <ParseSpecifier>...;
*
* leaves the ParseSpecifierarations in the symbol table pointed to by
* table and returns the number of bytes declared. al is the
* allocation type to assign, ilc is the initial location
* counter. if al is sc_member then no initialization will
* be processed. ztype should be bt_struct for normal and in
* structure ParseSpecifierarations and sc_union for in union ParseSpecifierarations.
*/
int declare(TABLE *table,int al,int ilc,int ztype)
{
SYM *sp, *sp1, *sp2;
TYP *dhead;
 
static long old_nbytes;
int nbytes;
 
nbytes = 0;
ParseSpecifier(table);
dhead = head;
for(;;) {
declid = 0;
bit_width = -1;
ParseDeclarationPrefix(ztype==bt_union);
if( declid != 0) { /* otherwise just struct tag... */
sp = allocSYM();
sp->name = declid;
sp->storage_class = al;
if (bit_width > 0 && bit_offset > 0) {
// share the storage word with the previously defined field
nbytes = old_nbytes - ilc;
}
old_nbytes = ilc + nbytes;
if (al != sc_member) {
// sp->isTypedef = isTypedef;
if (isTypedef)
sp->storage_class = sc_typedef;
isTypedef = FALSE;
}
while( (ilc + nbytes) % alignment(head)) {
if( al != sc_member && al != sc_external && al != sc_auto) {
dseg();
GenerateByte(0);
}
++nbytes;
}
if( al == sc_static)
sp->value.i = nextlabel++;
else if( ztype == bt_union)
sp->value.i = ilc;
else if( al != sc_auto )
sp->value.i = ilc + nbytes;
else
sp->value.i = -(ilc + nbytes + head->size);
 
if (bit_width == -1)
sp->tp = head;
else {
sp->tp = allocTYP();
*(sp->tp) = *head;
sp->tp->type = bt_bitfield;
sp->tp->size = head->size;//tp_int.size;
sp->tp->bit_width = bit_width;
sp->tp->bit_offset = bit_offset;
}
 
if(
(sp->tp->type == bt_func) &&
sp->storage_class == sc_global )
sp->storage_class = sc_external;
if(ztype == bt_union)
nbytes = imax(nbytes,sp->tp->size);
else if(al != sc_external)
nbytes += sp->tp->size;
if( sp->tp->type == bt_ifunc && (sp1 = search(sp->name,table)) != 0 &&
sp1->tp->type == bt_func )
{
sp1->tp = sp->tp;
sp1->storage_class = sp->storage_class;
// sp1->value.i = sp->value.i;
sp1->IsPrototype = sp->IsPrototype;
sp = sp1;
}
else {
sp2 = search(sp->name,table);
if (sp2 == NULL)
insert(sp,table);
else {
if (funcdecl==2)
sp2->tp = sp->tp;
//else if (!sp2->IsPrototype)
// insert(sp,table);
}
}
if( sp->tp->type == bt_ifunc) { /* function body follows */
ParseFunction(sp);
return nbytes;
}
if( (al == sc_global || al == sc_static) &&
sp->tp->type != bt_func && sp->storage_class!=sc_typedef)
doinit(sp);
}
if (funcdecl==TRUE) {
if (lastst==comma || lastst==semicolon)
break;
if (lastst==closepa)
goto xit1;
}
else if (catchdecl==TRUE) {
if (lastst==closepa)
goto xit1;
}
else if (lastst == semicolon)
break;
 
needpunc(comma);
if(declbegin(lastst) == 0)
break;
head = dhead;
}
NextToken();
xit1:
return nbytes;
}
 
int declbegin(int st)
{
return st == star || st == id || st == openpa || st == openbr;
}
 
void ParseGlobalDeclarations()
{
funcdecl = FALSE;
for(;;) {
switch(lastst) {
case id:
case kw_interrupt:
case kw_pascal:
case kw_nocall:
case kw_oscall:
case kw_typedef:
case kw_byte: case kw_char: case kw_int: case kw_short: case kw_unsigned: case kw_signed:
case kw_long: case kw_struct: case kw_union:
case kw_enum: case kw_void:
case kw_float: case kw_double:
lc_static += declare(&gsyms,sc_global,lc_static,bt_struct);
break;
case kw_register:
NextToken();
error(ERR_ILLCLASS);
lc_static += declare(&gsyms,sc_global,lc_static,bt_struct);
break;
case kw_private:
case kw_static:
NextToken();
lc_static += declare(&gsyms,sc_static,lc_static,bt_struct);
break;
case kw_extern:
NextToken();
if (lastst==kw_oscall || lastst==kw_interrupt || lastst==kw_nocall)
NextToken();
++global_flag;
declare(&gsyms,sc_external,0,bt_struct);
--global_flag;
break;
default:
return;
}
}
}
 
void ParseParameterDeclarations(int fd)
{
funcdecl = fd;
for(;;) {
switch(lastst) {
case kw_interrupt:
case kw_nocall:
case kw_oscall:
case kw_pascal:
case kw_typedef:
error(ERR_ILLCLASS);
declare(&lsyms,sc_auto,0,bt_struct);
break;
case id:
case kw_byte: case kw_char: case kw_int: case kw_short: case kw_unsigned: case kw_signed:
case kw_long: case kw_struct: case kw_union:
case kw_enum: case kw_void:
case kw_float: case kw_double:
declare(&lsyms,sc_auto,0,bt_struct);
break;
case kw_static:
NextToken();
error(ERR_ILLCLASS);
lc_static += declare(&gsyms,sc_static,lc_static,bt_struct);
break;
case kw_extern:
NextToken();
error(ERR_ILLCLASS);
if (lastst==kw_oscall || lastst==kw_interrupt || lastst == kw_nocall)
NextToken();
++global_flag;
declare(&gsyms,sc_external,0,bt_struct);
--global_flag;
break;
default:
return;
}
}
}
 
 
void ParseAutoDeclarations()
{
SYM *sp;
 
funcdecl = FALSE;
for(;;) {
switch(lastst) {
case kw_interrupt:
case kw_nocall:
case kw_oscall:
case kw_pascal:
case kw_typedef:
error(ERR_ILLCLASS);
lc_auto += declare(&lsyms,sc_auto,lc_auto,bt_struct);
break;
case id: //return;
sp = search(lastid,&gsyms[0]);
if (sp) {
if (sp->storage_class==sc_typedef) {
lc_auto += declare(&lsyms,sc_auto,lc_auto,bt_struct);
break;
}
}
return;
case kw_register:
NextToken();
case kw_byte: case kw_char: case kw_int: case kw_short: case kw_unsigned: case kw_signed:
case kw_long: case kw_struct: case kw_union:
case kw_enum: case kw_void:
case kw_float: case kw_double:
lc_auto += declare(&lsyms,sc_auto,lc_auto,bt_struct);
break;
case kw_static:
NextToken();
lc_static += declare(&lsyms,sc_static,lc_static,bt_struct);
break;
case kw_extern:
NextToken();
if (lastst==kw_oscall || lastst==kw_interrupt || lastst == kw_nocall)
NextToken();
++global_flag;
declare(&gsyms,sc_external,0,bt_struct);
--global_flag;
break;
default:
return;
}
}
}
 
/*
* main compiler routine. this routine parses all of the
* ParseSpecifierarations using declare which will call funcbody as
* functions are encountered.
*/
void compile()
{
while(lastst != eof)
{
ParseGlobalDeclarations();
if( lastst != eof)
NextToken();
}
dumplits();
}
 
/Analyze.c
0,0 → 1,578
#include <stdio.h>
#include "c.h"
#include "expr.h"
#include "Statement.h"
#include "gen.h"
#include "cglbdec.h"
 
/*
* 68000 C compiler
*
* Copyright 1984, 1985, 1986 Matthew Brandt.
* all commercial rights reserved.
*
* This compiler is intended as an instructive tool for personal use. Any
* use for profit without the written consent of the author is prohibited.
*
* This compiler may be distributed freely for non-commercial use as long
* as this notice stays intact. Please forward any enhancements or questions
* to:
*
* Matthew Brandt
* Box 920337
* Norcross, Ga 30092
*/
 
/*******************************************************
Modified to support Raptor64 'C64' language
by Robert Finch
robfinch@opencores.org
*******************************************************/
 
extern int popcnt(int m);
 
/*
* this module will step through the parse tree and find all
* optimizable expressions. at present these expressions are
* limited to expressions that are valid throughout the scope
* of the function. the list of optimizable expressions is:
*
* constants
* global and static addresses
* auto addresses
* contents of auto addresses.
*
* contents of auto addresses are valid only if the address is
* never referred to without dereferencing.
*
* scan will build a list of optimizable expressions which
* opt1 will replace during the second optimization pass.
*/
 
static CSE *olist; /* list of optimizable expressions */
 
/*
* equalnode will return 1 if the expressions pointed to by
* node1 and node2 are equivalent.
*/
static int equalnode(ENODE *node1, ENODE *node2)
{
// if( node1 == 0 || node2 == 0 )
// return 0;
// if( node1->nodetype != node2->nodetype )
// return 0;
// if( (node1->nodetype == en_icon || node1->nodetype == en_labcon ||
// node1->nodetype == en_nacon || node1->nodetype == en_autocon) &&
// node1->v.i == node2->v.i )
// return 1;
// if( IsLValue(node1) && equalnode(node1->v.p[0], node2->v.p[0]) )
// return 1;
// return 0;
//}
if (node1 == NULL || node2 == NULL)
return FALSE;
if (node1->nodetype != node2->nodetype)
return FALSE;
switch (node1->nodetype) {
case en_icon:
case en_labcon:
case en_autocon:
return (node1->i == node2->i);
case en_nacon:
return (!strcmp(node1->sp, node2->sp));
default:
if( IsLValue(node1) && equalnode(node1->p[0], node2->p[0]) )
return TRUE;
return FALSE;
}
}
 
/*
* SearchCSEList will search the common expression table for an entry
* that matches the node passed and return a pointer to it.
*/
static CSE *SearchCSEList(ENODE *node)
{
CSE *csp;
 
csp = olist;
while( csp != NULL ) {
if( equalnode(node,csp->exp) )
return csp;
csp = csp->next;
}
return NULL;
}
 
/*
* copy the node passed into a new enode so it wont get
* corrupted during substitution.
*/
static ENODE *DuplicateEnode(ENODE *node)
{
ENODE *temp;
 
if( node == NULL )
return NULL;
temp = allocEnode();
memcpy(temp,node,sizeof(ENODE)); // copy all the fields
return temp;
}
 
/*
* InsertNodeIntoCSEList will enter a reference to an expression node into the
* common expression table. duse is a flag indicating whether or not
* this reference will be dereferenced.
*/
CSE *InsertNodeIntoCSEList(ENODE *node, int duse)
{
CSE *csp;
 
if( (csp = SearchCSEList(node)) == NULL ) { /* add to tree */
csp = allocCSE();
csp->next = olist;
csp->uses = 1;
csp->duses = (duse != 0);
csp->exp = DuplicateEnode(node);
csp->voidf = 0;
csp->reg = 0;
olist = csp;
return csp;
}
++(csp->uses);
if( duse )
++(csp->duses);
return csp;
}
 
/*
* voidauto will void an auto dereference node which points to
* the same auto constant as node.
*/
CSE *voidauto(ENODE *node)
{
CSE *csp;
 
csp = olist;
while( csp != NULL ) {
if( IsLValue(csp->exp) && equalnode(node,csp->exp->p[0]) ) {
if( csp->voidf )
return NULL;
csp->voidf = 1;
return csp;
}
csp = csp->next;
}
return NULL;
}
 
/*
* scanexpr will scan the expression pointed to by node for optimizable
* subexpressions. when an optimizable expression is found it is entered
* into the tree. if a reference to an autocon node is scanned the
* corresponding auto dereferenced node will be voided. duse should be
* set if the expression will be dereferenced.
*/
static void scanexpr(ENODE *node, int duse)
{
CSE *csp, *csp1;
 
if( node == NULL )
return;
 
switch( node->nodetype ) {
case en_icon:
case en_labcon:
case en_nacon:
InsertNodeIntoCSEList(node,duse);
break;
case en_autocon:
if( (csp = voidauto(node)) != NULL ) {
csp1 = InsertNodeIntoCSEList(node,duse);
csp1->uses = (csp1->duses += csp->uses);
}
else
InsertNodeIntoCSEList(node,duse);
break;
case en_b_ref:
case en_c_ref:
case en_h_ref:
case en_w_ref:
case en_ub_ref:
case en_uc_ref:
case en_uh_ref:
case en_uw_ref:
case en_bfieldref:
case en_ubfieldref:
case en_cfieldref:
case en_ucfieldref:
case en_hfieldref:
case en_uhfieldref:
case en_wfieldref:
case en_uwfieldref:
if( node->p[0]->nodetype == en_autocon ) {
csp = InsertNodeIntoCSEList(node,duse);
if( csp->voidf )
scanexpr(node->p[0],1);
}
else
scanexpr(node->p[0],1);
break;
case en_cbc:
case en_cbh:
case en_cbw:
case en_cch:
case en_ccw:
case en_chw:
case en_uminus:
case en_compl: case en_ainc:
case en_adec: case en_not:
scanexpr(node->p[0],duse);
break;
case en_asadd: case en_assub:
case en_add: case en_sub:
scanexpr(node->p[0],duse);
scanexpr(node->p[1],duse);
break;
case en_mul: case en_mulu: case en_div: case en_udiv:
case en_shl: case en_shr: case en_shru:
case en_mod: case en_and:
case en_or: case en_xor:
case en_lor: case en_land:
case en_eq: case en_ne:
case en_gt: case en_ge:
case en_lt: case en_le:
case en_asmul: case en_asdiv:
case en_asmod: case en_aslsh:
case en_asrsh:
case en_asand: case en_asxor: case en_asor:
case en_cond:
case en_void: case en_assign:
scanexpr(node->p[0],0);
scanexpr(node->p[1],0);
break;
case en_fcall:
scanexpr(node->p[0],1);
scanexpr(node->p[1],0);
break;
}
}
 
/*
* scan will gather all optimizable expressions into the expression
* list for a block of statements.
*/
static void scan(Statement *block)
{
while( block != NULL ) {
switch( block->stype ) {
case st_return:
case st_throw:
case st_expr:
opt4(&block->exp);
scanexpr(block->exp,0);
break;
case st_while:
case st_until:
case st_do:
case st_dountil:
opt4(&block->exp);
scanexpr(block->exp,0);
case st_doloop:
case st_forever:
scan(block->s1);
break;
case st_for:
opt4(&block->initExpr);
scanexpr(block->initExpr,0);
opt4(&block->exp);
scanexpr(block->exp,0);
scan(block->s1);
opt4(&block->incrExpr);
scanexpr(block->incrExpr,0);
break;
case st_if:
opt4(&block->exp);
scanexpr(block->exp,0);
scan(block->s1);
scan(block->s2);
break;
case st_switch:
opt4(&block->exp);
scanexpr(block->exp,0);
scan(block->s1);
break;
case st_case:
scan(block->s1);
break;
case st_spinlock:
scan(block->s1);
break;
}
block = block->next;
}
}
 
/*
* exchange will exchange the order of two expression entries
* following c1 in the linked list.
*/
static void exchange(CSE **c1)
{
CSE *csp1, *csp2;
 
csp1 = *c1;
csp2 = csp1->next;
csp1->next = csp2->next;
csp2->next = csp1;
*c1 = csp2;
}
 
/*
* returns the desirability of optimization for a subexpression.
*/
int OptimizationDesireability(CSE *csp)
{
if( csp->voidf || (csp->exp->nodetype == en_icon &&
csp->exp->i < 256 && csp->exp->i >= 0))
return 0;
if( IsLValue(csp->exp) )
return 2 * csp->uses;
return csp->uses;
}
 
/*
* bsort implements a bubble sort on the expression list.
*/
int bsort(CSE **list)
{
CSE *csp1, *csp2;
int i;
 
csp1 = *list;
if( csp1 == NULL || csp1->next == NULL )
return FALSE;
i = bsort( &(csp1->next));
csp2 = csp1->next;
if( OptimizationDesireability(csp1) < OptimizationDesireability(csp2) ) {
exchange(list);
return TRUE;
}
return FALSE;
}
 
/*
* AllocateRegisterVars will allocate registers for the expressions that have
* a high enough desirability.
*/
void AllocateRegisterVars()
{
CSE *csp;
ENODE *exptr;
int reg, mask, rmask;
AMODE *ap, *ap2;
int nn;
 
reg = 11;
mask = 0;
rmask = 0;
while( bsort(&olist) ); /* sort the expression list */
csp = olist;
while( csp != NULL ) {
if( OptimizationDesireability(csp) < 3 ) // was < 3
csp->reg = -1;
// else if( csp->duses > csp->uses / 8 && reg < 18 ) // was / 4
else if( reg < 18 ) // was / 4
csp->reg = reg++;
else
csp->reg = -1;
if( csp->reg != -1 )
{
rmask = rmask | (1 << (31 - csp->reg));
mask = mask | (1 << csp->reg);
}
csp = csp->next;
}
if( mask != 0 ) {
if (bitsset(rmask) < 2) {
for (nn = 0; nn < 32; nn++)
if (rmask & (0x80000000 >> nn)) {
GenerateTriadic(op_subui,0,makereg(30),makereg(30),make_immed(8));
GenerateTriadic(op_sw,0,makereg(nn&31),make_indirect(30),NULL);
}
}
else {
GenerateTriadic(op_subui,0,makereg(30),makereg(30),make_immed(popcnt(mask)*8));
GenerateDiadic(op_sm,0,make_indirect(30),make_mask(mask),NULL);
}
}
save_mask = mask;
csp = olist;
while( csp != NULL ) {
if( csp->reg != -1 )
{ /* see if preload needed */
exptr = csp->exp;
if( !IsLValue(exptr) || (exptr->p[0]->i > 0) )
{
initstack();
ap = GenerateExpression(exptr,F_REG|F_IMMED,8);
ap2 = makereg(csp->reg);
if (ap->mode==am_immed)
GenerateTriadic(op_ori,0,ap2,makereg(0),ap);
else
GenerateDiadic(op_mov,0,ap2,ap);
ReleaseTempRegister(ap);
}
}
csp = csp->next;
}
}
 
/*
* repexpr will replace all allocated references within an expression
* with tempref nodes.
*/
void repexpr(ENODE *node)
{
struct cse *csp;
if( node == NULL )
return;
switch( node->nodetype ) {
case en_icon:
case en_nacon:
case en_labcon:
case en_autocon:
if( (csp = SearchCSEList(node)) != NULL )
if( csp->reg > 0 ) {
node->nodetype = en_regvar;
node->i = csp->reg;
}
break;
case en_b_ref:
case en_c_ref:
case en_h_ref:
case en_w_ref:
case en_ub_ref:
case en_uc_ref:
case en_uh_ref:
case en_uw_ref:
case en_bfieldref:
case en_ubfieldref:
case en_cfieldref:
case en_ucfieldref:
case en_hfieldref:
case en_uhfieldref:
case en_wfieldref:
case en_uwfieldref:
if( (csp = SearchCSEList(node)) != NULL ) {
if( csp->reg > 0 ) {
node->nodetype = en_regvar;
node->i = csp->reg;
}
else
repexpr(node->p[0]);
}
else
repexpr(node->p[0]);
break;
case en_cbc:
case en_cbh:
case en_cbw:
case en_cch:
case en_ccw:
case en_chw:
case en_uminus:
case en_not: case en_compl:
case en_ainc: case en_adec:
repexpr(node->p[0]);
break;
case en_add: case en_sub:
case en_mul: case en_mulu: case en_div: case en_udiv:
case en_mod: case en_shl: case en_shru:
case en_shr: case en_and:
case en_or: case en_xor:
case en_land: case en_lor:
case en_eq: case en_ne:
case en_lt: case en_le:
case en_gt: case en_ge:
case en_cond: case en_void:
case en_asadd: case en_assub:
case en_asmul: case en_asdiv:
case en_asor: case en_asand:
case en_asmod: case en_aslsh:
case en_asrsh: case en_fcall:
case en_assign:
repexpr(node->p[0]);
repexpr(node->p[1]);
break;
}
}
 
/*
* repcse will scan through a block of statements replacing the
* optimized expressions with their temporary references.
*/
void repcse(Statement *block)
{
while( block != NULL ) {
switch( block->stype ) {
case st_return:
case st_throw:
repexpr(block->exp);
break;
case st_expr:
repexpr(block->exp);
break;
case st_while:
case st_until:
case st_do:
case st_dountil:
repexpr(block->exp);
case st_doloop:
case st_forever:
repcse(block->s1);
repcse(block->s2);
break;
case st_for:
repexpr(block->initExpr);
repexpr(block->exp);
repcse(block->s1);
repexpr(block->incrExpr);
break;
case st_if:
repexpr(block->exp);
repcse(block->s1);
repcse(block->s2);
break;
case st_switch:
repexpr(block->exp);
repcse(block->s1);
break;
case st_try:
case st_catch:
case st_case:
repcse(block->s1);
break;
case st_spinlock:
repcse(block->s1);
repcse(block->s2); // lockfail statement
break;
}
block = block->next;
}
}
 
/*
* opt1 is the externally callable optimization routine. it will
* collect and allocate common subexpressions and substitute the
* tempref for all occurrances of the expression within the block.
*
* optimizer is currently turned off...
*/
void opt1(Statement *block)
{
olist = NULL;
scan(block); /* collect expressions */
AllocateRegisterVars(); /* allocate registers */
repcse(block); /* replace allocated expressions */
}
/Symbol.c
0,0 → 1,81
// ============================================================================
// (C) 2012 Robert Finch
// All Rights Reserved.
// robfinch<remove>@opencores.org
//
// C64 - Raptor64 'C' derived language compiler
// - 64 bit CPU
//
// This source file is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file 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 this program. If not, see <http://www.gnu.org/licenses/>.
//
// ============================================================================
//
#include <stdio.h>
#include <string.h>
#include "c.h"
#include "expr.h"
#include "Statement.h"
#include "gen.h"
#include "cglbdec.h"
 
static unsigned __int8 hashadd(char *nm)
{
unsigned __int8 hsh;
 
for(hsh=0;*nm;nm++)
hsh += *nm;
return hsh;
}
 
SYM *search(char *na,TABLE *tbl)
{
SYM *thead;
if (tbl==&gsyms[0])
thead = gsyms[hashadd(na)].head;
else
thead = tbl->head;
while( thead != NULL) {
if (thead->name != NULL)
if(strcmp(thead->name,na) == 0)
return thead;
thead = thead->next;
}
return NULL;
}
 
SYM *gsearch(char *na)
{
SYM *sp;
 
if((sp = search(na,&lsyms)) == NULL)
sp = search(na,&gsyms[0]);
return sp;
}
 
void insert(SYM* sp, TABLE *table)
{
if (table==&gsyms[0])
table = &gsyms[hashadd(sp->name)];
if( search(sp->name,table) == NULL) {
if( table->head == NULL)
table->head = table->tail = sp;
else {
table->tail->next = sp;
table->tail = sp;
}
sp->next = NULL;
}
else
error(ERR_DUPSYM);
}
/MemoryManagement.c
0,0 → 1,148
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "c.h"
#include "expr.h"
#include "Statement.h"
#include "gen.h"
#include "cglbdec.h"
 
/*
* 68000 C compiler
*
* Copyright 1984, 1985, 1986 Matthew Brandt.
* all commercial rights reserved.
*
* This compiler is intended as an instructive tool for personal use. Any
* use for profit without the written consent of the author is prohibited.
*
* This compiler may be distributed freely for non-commercial use as long
* as this notice stays intact. Please forward any enhancements or questions
* to:
*
* Matthew Brandt
* Box 920337
* Norcross, Ga 30092
*/
/*******************************************************
Modified to support Raptor64 'C64' language
by Robert Finch
robfinch@opencores.org
*******************************************************/
 
#define BLKSIZE 4000
 
struct blk {
char name[8]; // string overwrite area
struct blk *next;
char m[1]; /* memory area */
};
 
static int glbsize = 0, /* size left in current global block */
locsize = 0, /* size left in current local block */
glbindx = 0, /* global index */
locindx = 0; /* local index */
 
static struct blk *locblk = 0, /* pointer to local block */
*glbblk = 0; /* pointer to global block */
 
char *xalloc(int siz)
{
struct blk *bp;
char *rv;
 
while(siz % 8) // align word
siz++;
if( global_flag ) {
if( glbsize >= siz ) {
rv = &(glbblk->m[glbindx]);
glbsize -= siz;
glbindx += siz;
return rv;
}
else {
bp = calloc(1,sizeof(struct blk) + BLKSIZE);
if( bp == NULL )
{
printf(" not enough memory.\n");
exit(1);
}
strcpy(bp->name,"C64 ");
bp->next = glbblk;
glbblk = bp;
glbsize = BLKSIZE - siz;
glbindx = siz;
return glbblk->m;
}
}
else {
if( locsize >= siz ) {
rv = &(locblk->m[locindx]);
locsize -= siz;
locindx += siz;
return rv;
}
else {
bp = calloc(1,sizeof(struct blk) + BLKSIZE);
if( bp == NULL )
{
printf(" not enough local memory.\n");
exit(1);
}
strcpy(bp->name,"C64 ");
bp->next = locblk;
locblk = bp;
locsize = BLKSIZE - siz;
locindx = siz;
return locblk->m;
}
}
}
 
void ReleaseLocalMemory()
{
struct blk *bp1, *bp2;
int blkcnt;
blkcnt = 0;
bp1 = locblk;
while( bp1 != NULL ) {
bp2 = bp1->next;
free( bp1 );
++blkcnt;
bp1 = bp2;
}
locblk = NULL;
locsize = 0;
lsyms.head = NULL;
lsyms.tail = NULL;
printf(" releasing %d bytes local tables.\n",blkcnt * BLKSIZE);
}
 
void ReleaseGlobalMemory()
{
struct blk *bp1, *bp2;
int blkcnt;
bp1 = glbblk;
blkcnt = 0;
while( bp1 != 0 ) {
bp2 = bp1->next;
free(bp1);
++blkcnt;
bp1 = bp2;
}
glbblk = NULL;
glbsize = 0;
// gsyms.head = NULL; /* clear global symbol table */
// gsyms.tail = NULL;
memset(gsyms,0,sizeof(gsyms));
printf(" releasing %d bytes global tables.\n",blkcnt * BLKSIZE);
strtab = 0; /* clear literal table */
}
 
SYM *allocSYM() { return (SYM *)xalloc(sizeof(SYM)); };
TYP *allocTYP() { return (TYP *)xalloc(sizeof(TYP)); };
struct snode *allocSnode() { return (struct snode *)xalloc(sizeof(struct snode)); };
ENODE *allocEnode() { return (ENODE *)xalloc(sizeof(ENODE)); };
AMODE *allocAmode() { return (AMODE *)xalloc(sizeof(AMODE)); };
CSE *allocCSE() { return (CSE *)xalloc(sizeof(CSE)); };
 
/Initializers.c
0,0 → 1,219
#include <stdio.h>
#include <string.h>
#include "c.h"
#include "expr.h"
#include "Statement.h"
#include "gen.h"
#include "cglbdec.h"
/*
* 68000 C compiler
*
* Copyright 1984, 1985, 1986 Matthew Brandt.
* all commercial rights reserved.
*
* This compiler is intended as an instructive tool for personal use. Any
* use for profit without the written consent of the author is prohibited.
*
* This compiler may be distributed freely for non-commercial use as long
* as this notice stays intact. Please forward any enhancements or questions
* to:
*
* Matthew Brandt
* Box 920337
* Norcross, Ga 30092
*/
/*******************************************************
Modified to support Raptor64 'C64' language
by Robert Finch
robfinch@opencores.org
*******************************************************/
 
int InitializeType(TYP *tp);
int InitializeStructure(TYP *tp);
int initbyte();
int initchar();
int initshort();
int initlong();
int InitializePointer();
void endinit();
int InitializeArray(TYP *tp);
 
void doinit(SYM *sp)
{
dseg(); /* initialize into data segment */
nl(); /* start a new line in object */
if(sp->storage_class == sc_static)
put_label(sp->value.i);
else
gen_strlab(sp->name);
if( lastst != assign) {
genstorage(sp->tp->size);
}
else {
NextToken();
InitializeType(sp->tp);
}
endinit();
}
 
int InitializeType(TYP *tp)
{
int nbytes;
 
switch(tp->type) {
case bt_byte:
nbytes = initbyte();
break;
case bt_char:
case bt_enum:
nbytes = initchar();
break;
case bt_short:
nbytes = initshort();
break;
case bt_pointer:
if( tp->val_flag)
nbytes = InitializeArray(tp);
else
nbytes = InitializePointer();
break;
case bt_long:
nbytes = initlong();
break;
case bt_struct:
nbytes = InitializeStructure(tp);
break;
default:
error(ERR_NOINIT);
nbytes = 0;
}
return nbytes;
}
 
int InitializeArray(TYP *tp)
{
int nbytes;
char *p;
 
nbytes = 0;
if( lastst == begin) {
NextToken(); /* skip past the brace */
while(lastst != end) {
nbytes += InitializeType(tp->btp);
if( lastst == comma)
NextToken();
else if( lastst != end)
error(ERR_PUNCT);
}
NextToken(); /* skip closing brace */
}
else if( lastst == sconst && tp->btp->type == bt_char) {
nbytes = strlen(laststr) * 2 + 2;
p = laststr;
while( *p )
GenerateChar(*p++);
GenerateChar(0);
NextToken();
}
else if( lastst != semicolon)
error(ERR_ILLINIT);
if( nbytes < tp->size) {
genstorage( tp->size - nbytes);
nbytes = tp->size;
}
else if( tp->size != 0 && nbytes > tp->size)
error(ERR_INITSIZE); /* too many initializers */
return nbytes;
}
 
int InitializeStructure(TYP *tp)
{
SYM *sp;
int nbytes;
 
needpunc(begin);
nbytes = 0;
sp = tp->lst.head; /* start at top of symbol table */
while(sp != 0) {
while(nbytes < sp->value.i) { /* align properly */
// nbytes += GenerateByte(0);
GenerateByte(0);
// nbytes++;
}
nbytes += InitializeType(sp->tp);
if( lastst == comma)
NextToken();
else if(lastst == end)
break;
else
error(ERR_PUNCT);
sp = sp->next;
}
if( nbytes < tp->size)
genstorage( tp->size - nbytes);
needpunc(end);
return tp->size;
}
 
int initbyte()
{
GenerateByte(GetIntegerExpression());
return 1;
}
 
int initchar()
{
GenerateChar(GetIntegerExpression());
return 2;
}
 
int initshort()
{
GenerateWord(GetIntegerExpression());
return 4;
}
 
int initlong()
{
GenerateLong(GetIntegerExpression());
return 8;
}
 
int InitializePointer()
{
SYM *sp;
 
if(lastst == and) { /* address of a variable */
NextToken();
if( lastst != id)
error(ERR_IDEXPECT);
else if( (sp = gsearch(lastid)) == NULL)
error(ERR_UNDEFINED);
else {
NextToken();
if( lastst == plus || lastst == minus)
GenerateReference(sp,GetIntegerExpression());
else
GenerateReference(sp,0);
if( sp->storage_class == sc_auto)
error(ERR_NOINIT);
}
}
else if(lastst == sconst) {
GenerateLabelReference(stringlit(laststr));
NextToken();
}
else
GenerateLong(GetIntegerExpression());
endinit();
return 8; /* pointers are 4 bytes long */
}
 
void endinit()
{
if( lastst != comma && lastst != semicolon && lastst != end) {
error(ERR_PUNCT);
while( lastst != comma && lastst != semicolon && lastst != end)
NextToken();
}
}
/Statement.h
0,0 → 1,22
/* statement node descriptions */
 
enum e_stmt {
st_expr, st_while,
st_until, st_forever, st_firstcall, st_asm,
st_dountil, st_doloop,
st_try, st_catch, st_throw, st_critical, st_spinlock, st_spinunlock,
st_for,
st_do, st_if, st_switch, st_default,
st_case, st_goto, st_break, st_continue, st_label,
st_return, st_vortex, st_intoff, st_inton, st_stop };
 
typedef struct snode {
__int8 stype;
struct snode *next; /* next statement */
ENODE *exp; /* condition or expression */
ENODE *initExpr; /* initialization expression - for loops */
ENODE *incrExpr; /* increment expression - for loops */
struct snode *s1, *s2; /* internal statements */
__int64 *label; /* label number for goto */
} Statement;
 
/Code.h
0,0 → 1,26
/*
* code structure definitions.
*/
 
enum address_mode {
am_const, am_label, am_string, am_temp, am_auto,
am_defcon, am_deflab, am_defstr, am_deftemp, am_defauto,
am_none };
 
enum instruction {
i_move, i_add, i_sub, i_mul, i_div, i_mod, i_and, i_or,
i_xor, i_shl, i_shr, i_jmp, i_jeq, i_jne, i_jlt, i_jle,
i_jgt, i_jge, i_call, i_enter, i_ret, i_table, i_label };
 
union aval {
int i;
char *s;
};
 
struct inst {
struct inst *fwd, *back;
int opcode, size;
char sm0, sm1, dm;
union aval sv0, sv1, dv;
};
 
/ParseFunction.c
0,0 → 1,191
#include <stdio.h>
#include "c.h"
#include "expr.h"
#include "Statement.h"
#include "gen.h"
#include "cglbdec.h"
 
/*
* 68000 C compiler
*
* Copyright 1984, 1985, 1986 Matthew Brandt.
* all commercial rights reserved.
*
* This compiler is intended as an instructive tool for personal use. Any
* use for profit without the written consent of the author is prohibited.
*
* This compiler may be distributed freely for non-commercial use as long
* as this notice stays intact. Please forward any enhancements or questions
* to:
*
* Matthew Brandt
* Box 920337
* Norcross, Ga 30092
*/
/*******************************************************
Copyright 2012 Robert Finch
Modified to support Raptor64 'C64' language
by Robert Finch
robfinch@opencores.org
*******************************************************/
 
 
extern int funcdecl;
extern char *names[20];
extern int nparms;
 
void ParseFunctionBody(SYM *sp);
void funcbottom();
 
/* function compilation routines */
 
/*
* funcbody starts with the current symbol being either
* the first parameter id or the begin for the local
* block. If begin is the current symbol then funcbody
* assumes that the function has no parameters.
*/
void ParseFunction(SYM *sp)
{
int poffset, i;
int oldglobal;
SYM *sp1, *sp2, *makeint();
 
oldglobal = global_flag;
global_flag = 0;
poffset = 24; /* size of return block */
nparms = 0;
if(lastst == id || 1) { /* declare parameters */
//while(lastst == id) {
// names[nparms++] = litlate(lastid);
// NextToken();
// if( lastst == comma)
// NextToken();
// else
// break;
// }
//needpunc(closepa);
// dodecl(sc_member); /* declare parameters */
sp->parms = NULL;
ParseParameterDeclarations(1);
for(i = 0;i < nparms;++i) {
if( (sp1 = search(names[i],&lsyms)) == NULL)
sp1 = makeint(names[i]);
//if( sp1->tp->size < 8 )
//{
// sp1->value.i = poffset;// + (8 - sp1->tp->size);
// poffset += 8;
//}
//else
//{
// sp1->value.i = poffset;
// poffset += sp1->tp->size;
//}
sp1->value.i = poffset;
poffset += 8;
sp1->storage_class = sc_auto;
sp1->nextparm = NULL;
// record parameter list
if (sp->parms == NULL) {
sp->parms = sp1;
}
else {
sp1->nextparm = sp->parms;
sp->parms = sp1;
}
}
}
if (lastst == closepa)
NextToken();
if (lastst == semicolon) { // Function prototype
sp->IsPrototype = 1;
sp->IsNocall = isNocall;
sp->IsPascal = isPascal;
sp->IsInterrupt = isInterrupt;
sp->NumParms = nparms;
isPascal = FALSE;
isOscall = FALSE;
isInterrupt = FALSE;
isNocall = FALSE;
ReleaseLocalMemory(); /* release local symbols (parameters)*/
}
else if(lastst != begin) {
NextToken();
ParseParameterDeclarations(2);
sp->IsNocall = isNocall;
sp->IsPascal = isPascal;
sp->IsInterrupt = isInterrupt;
sp->NumParms = nparms;
ParseFunctionBody(sp);
funcbottom();
}
// error(ERR_BLOCK);
else {
sp->IsNocall = isNocall;
sp->IsPascal = isPascal;
sp->IsInterrupt = isInterrupt;
sp->NumParms = nparms;
ParseFunctionBody(sp);
funcbottom();
}
global_flag = oldglobal;
}
 
SYM *makeint(char *name)
{ SYM *sp;
TYP *tp;
sp = allocSYM();
tp = allocTYP();
tp->type = bt_long;
tp->size = 8;
tp->btp = 0;
tp->lst.head = 0;
tp->sname = 0;
sp->name = name;
sp->storage_class = sc_auto;
sp->tp = tp;
sp->IsPrototype = FALSE;
insert(sp,&lsyms);
return sp;
}
 
void check_table(SYM *head)
{
while( head != 0 ) {
if( head->storage_class == sc_ulabel )
fprintf(list,"*** UNDEFINED LABEL - %s\n",head->name);
head = head->next;
}
}
 
void funcbottom()
{
nl();
check_table(&lsyms);
lc_auto = 0;
fprintf(list,"\n\n*** local symbol table ***\n\n");
ListTable(&lsyms,0);
fprintf(list,"\n\n\n");
ReleaseLocalMemory(); /* release local symbols */
isPascal = FALSE;
isOscall = FALSE;
isInterrupt = FALSE;
isNocall = FALSE;
}
 
void ParseFunctionBody(SYM *sp)
{
needpunc(begin);
ParseAutoDeclarations();
cseg();
if (sp->storage_class == sc_static)
put_label((unsigned int) sp->value.i);
else
gen_strlab(sp->name);
currentFn = sp;
currentFn->IsLeaf = TRUE;
currentFn->DoesThrow = FALSE;
GenerateFunction(sp, ParseCompoundStatement());
// if (optimize)
flush_peep();
}
/IdentifyKeyword.c
0,0 → 1,208
// ============================================================================
// (C) 2012 Robert Finch
// All Rights Reserved.
// robfinch<remove>@opencores.org
//
// C64 - Raptor64 'C' derived language compiler
// - 64 bit CPU
//
// This source file is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file 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 this program. If not, see <http://www.gnu.org/licenses/>.
//
// ============================================================================
//
#include <stdio.h>
#include "c.h"
#include "expr.h"
#include "gen.h"
#include "cglbdec.h"
 
int IdentifyKeyword()
{
char *p = lastid;
 
if (p[0]=='i') { // if,int,inton,intoff,interrupt,icache
if (p[1]=='f' && p[2]=='\0')
return lastst = kw_if;
if (p[1]=='n' && p[2]=='t' && p[3]=='\0')
return lastst = kw_int;
if (p[1]=='n' && p[2]=='t' && p[3]=='o' && p[4]=='n' && p[5]=='\0')
return lastst = kw_inton;
if (p[1]=='n' && p[2]=='t' && p[3]=='o' && p[4]=='f' && p[5]=='f' && p[6]=='\0')
return lastst = kw_intoff;
if (p[1]=='n' && p[2]=='t' && p[3]=='e' && p[4]=='r' && p[5]=='r' && p[6]=='u' && p[7]=='p' && p[8]=='t' && p[9]=='\0')
return lastst = kw_interrupt;
if (p[1]=='c' && p[2]=='a' && p[3]=='c' && p[4]=='h' && p[5]=='e' && p[6]=='\0')
return lastst = kw_icache;
}
 
if (p[0]=='b' && p[1]=='r' && p[2]=='e' && p[3]=='a' && p[4]=='k' && p[5]=='\0')
return lastst = kw_break;
if (p[0]=='b' && p[1]=='y' && p[2]=='t' && p[3]=='e' && p[4]=='\0')
return lastst = kw_byte;
if (p[0]=='w' && p[1]=='h' && p[2]=='i' && p[3]=='l' && p[4]=='e' && p[5]=='\0')
return lastst = kw_while;
 
if (p[0]=='d') { // do,default,double,dcache
if (p[1]=='o' && p[2]=='\0')
return lastst = kw_do;
if (p[1]=='o' && p[2]=='u' && p[3]=='b' && p[4]=='l' && p[5]=='e' && p[6]=='\0')
return lastst = kw_double;
if (p[1]=='e' && p[2]=='f' && p[3]=='a' && p[4]=='u' && p[5]=='l' && p[6]=='t' && p[7]=='\0')
return lastst = kw_default;
if (p[1]=='c' && p[2]=='a' && p[3]=='c' && p[4]=='h' && p[5]=='e' && p[6]=='\0')
return lastst = kw_dcache;
}
 
if (p[0]=='o') { // or,oscall
if (p[1]=='r' && p[2]=='\0')
return lastst = lor;
if (p[1]=='s' && p[2]=='c' && p[3]=='a' && p[4]=='l' && p[5]=='l' && p[6]=='\0')
return lastst = kw_oscall;
}
 
if (p[0]=='c') { // case,catch,char,continue
if(p[1]=='a' && p[2]=='s' && p[3]=='e' && p[4]=='\0')
return lastst = kw_case;
if(p[1]=='a' && p[2]=='t' && p[3]=='c' && p[4]=='h' && p[5]=='\0')
return lastst = kw_catch;
if(p[1]=='h' && p[2]=='a' && p[3]=='r' && p[4]=='\0')
return lastst = kw_char;
if (p[1]=='o' && p[2]=='n' && p[3]=='t' && p[4]=='i' && p[5]=='n' && p[6]=='u' && p[7]=='e' && p[8]=='\0')
return lastst = kw_continue;
if (p[1]=='r' && p[2]=='i' && p[3]=='t' && p[4]=='i' && p[5]=='c' && p[6]=='a' && p[7]=='l' && p[8]=='\0')
return lastst = kw_critical;
}
 
if (p[0]=='l') { // long,loop,lockfail
if (p[1]=='o' && p[2]=='n' && p[3]=='g' && p[4]=='\0')
return lastst = kw_long;
if (p[1]=='o' && p[2]=='o' && p[3]=='p' && p[4]=='\0')
return lastst = kw_loop;
if (p[1]=='o' && p[2]=='c' && p[3]=='k' && p[4]=='f' && p[5]=='a' && p[6]=='i' && p[7]=='l' && p[8]=='\0')
return lastst = kw_lockfail;
}
 
if (p[0]=='s') { // switch,short,static,stop,struct,sizeof,signed
if (p[1]=='w' && p[2]=='i' && p[3]=='t' && p[4]=='c' && p[5]=='h' && p[6]=='\0')
return lastst = kw_switch;
if (p[1]=='t' && p[2]=='a' && p[3]=='t' && p[4]=='i' && p[5]=='c' && p[6]=='\0')
return lastst = kw_static;
if (p[1]=='h' && p[2]=='o' && p[3]=='r' && p[4]=='t' && p[5]=='\0')
return lastst = kw_short;
if (p[1]=='t' && p[2]=='o' && p[3]=='p' && p[4]=='\0')
return lastst = kw_stop;
if (p[1]=='t' && p[2]=='r' && p[3]=='u' && p[4]=='c' && p[5]=='t' && p[6]=='\0')
return lastst = kw_struct;
if (p[1]=='i' && p[2]=='z' && p[3]=='e' && p[4]=='o' && p[5]=='f' && p[6]=='\0')
return lastst = kw_sizeof;
if (p[1]=='i' && p[2]=='g' && p[3]=='n' && p[4]=='e' && p[5]=='d' && p[6]=='\0')
return lastst = kw_signed;
}
 
if (p[0]=='t') { // typedef,typenum,throw,then,try
if (p[1]=='y' && p[2]=='p' && p[3]=='e' && p[4]=='d' && p[5]=='e' && p[6]=='f' && p[7]=='\0')
return lastst = kw_typedef;
if (p[1]=='y' && p[2]=='p' && p[3]=='e' && p[4]=='n' && p[5]=='u' && p[6]=='n' && p[7]=='\0')
return lastst = kw_typenum;
if (p[1]=='h' && p[2]=='r' && p[3]=='o' && p[4]=='w' && p[5]=='\0')
return lastst = kw_throw;
if (p[1]=='h' && p[2]=='e' && p[3]=='n' && p[4]=='\0')
return lastst = kw_then;
if (p[1]=='r' && p[2]=='y' && p[3]=='\0')
return lastst = kw_try;
}
 
if (p[0]=='g' && p[1]=='o' && p[2]=='t' && p[3]=='o' && p[4]=='\0')
return lastst = kw_goto;
if (p[0]=='j' && p[1]=='u' && p[2]=='m' && p[3]=='p' && p[4]=='\0')
return lastst = kw_goto;
 
if (p[0]=='e') { // else,enum,extern
if (p[1]=='l' && p[2]=='s' && p[3]=='e' && p[4]=='\0')
return lastst = kw_else;
if (p[1]=='l' && p[2]=='s' && p[3]=='i' && p[4]=='f' && p[5]=='\0')
return lastst = kw_elsif;
if (p[1]=='n' && p[2]=='u' && p[3]=='m' && p[4]=='\0')
return lastst = kw_enum;
if (p[1]=='x' && p[2]=='t' && p[3]=='e' && p[4]=='r' && p[5]=='n' && p[6]=='\0')
return lastst = kw_extern;
}
if (p[0]=='a') { // and,asm
if (p[1]=='n' && p[2]=='d' && p[3]=='\0')
return lastst = land;
if (p[1]=='s' && p[2]=='m' && p[3]=='\0')
return lastst = kw_asm;
}
if (p[0]=='v' && p[1]=='o' && p[2]=='i' && p[3]=='d' && p[4]=='\0')
return lastst = kw_void;
if (p[0]=='r' && p[1]=='e') { // return,register
if (p[2]=='t' && p[3]=='u' && p[4]=='r' && p[5]=='n' && p[6]=='\0')
return lastst = kw_return;
if (p[2]=='g' && p[3]=='i' && p[4]=='s' && p[5]=='t' && p[6]=='e' && p[7]=='r' && p[8]=='\0')
return lastst = kw_register;
}
if (p[0]=='l' && p[1]=='o' && p[2]=='o' && p[3]=='p' && p[4]=='\0')
return lastst = kw_loop;
if (p[0]=='u') { // unsigned,union,until
if (p[1]=='n' && p[2]=='s' && p[3]=='i' && p[4]=='g' && p[5]=='n' && p[6]=='e' && p[7]=='d' && p[8]=='\0')
return lastst = kw_unsigned;
if (p[1]=='n' && p[2]=='i' && p[3]=='o' && p[4]=='n' && p[5]=='\0')
return lastst = kw_union;
if (p[1]=='n' && p[2]=='t' && p[3]=='i' && p[4]=='l' && p[5]=='\0')
return lastst = kw_until;
}
if (p[0]=='f') { // float,forever,for,fallthru,firstcall
if (p[1]=='o' && p[2]=='r' && p[3]=='\0')
return lastst = kw_for;
if (p[1]=='l' && p[2]=='o' && p[3]=='a' && p[4]=='t' && p[5]=='\0')
return lastst = kw_float;
if (p[1]=='o' && p[2]=='r' && p[3]=='e' && p[4]=='v' && p[5]=='e' && p[6]=='r' && p[7]=='\0')
return lastst = kw_forever;
if (p[1]=='a' && p[2]=='l' && p[3]=='l' && p[4]=='t' && p[5]=='h' && p[6]=='r' && p[7]=='u' && p[8]=='\0')
return lastst = kw_fallthru;
if (p[1]=='i' && p[2]=='r' && p[3]=='s' && p[4]=='t' && p[5]=='c' && p[6]=='a' && p[7]=='l' && p[8]=='l' && p[9]=='\0')
return lastst = kw_firstcall;
}
if (p[0]=='m' && p[1]=='o' && p[2]=='d' && p[3]=='\0')
return lastst = modop;
 
if (p[0]=='p') { // private,public,pascal
if (p[1]=='r' && p[2]=='i' && p[3]=='v' && p[4]=='a' && p[5]=='t' && p[6]=='e' && p[7]=='\0')
return lastst = kw_private;
if (p[1]=='u' && p[2]=='b' && p[3]=='l' && p[4]=='i' && p[5]=='c' && p[6]=='\0')
return lastst = kw_public;
if (p[1]=='a' && p[2]=='s' && p[3]=='c' && p[4]=='a' && p[5]=='l' && p[6]=='\0')
return lastst = kw_pascal;
}
if (p[0]=='n') { // nocall
if (p[1]=='o' && p[2]=='c' && p[3]=='a' && p[4]=='l' && p[5]=='l' && p[6]=='\0')
return lastst = kw_nocall;
}
// __spinlock,__spinunlock
if (p[0]=='s' && p[1]=='p' && p[2]=='i' && p[3]=='n' && p[4]=='l' && p[5]=='o' && p[6]=='c' && p[7]=='k' && p[8]=='\0')
return lastst = kw_spinlock;
if (p[0]=='s' && p[1]=='p' && p[2]=='i' && p[3]=='n' && p[4]=='u' && p[5]=='n' && p[6]=='l' && p[7]=='o' && p[8]=='c' && p[9]=='k' && p[10]=='\0')
return lastst = kw_spinunlock;
 
if (p[0]=='f' && p[1]=='a' && p[2]=='l' && p[3]=='s' && p[4]=='e' && p[5]=='\0') {
ival = 0;
return lastst = iconst;
}
if (p[0]=='t' && p[1]=='r' && p[2]=='u' && p[3]=='e' && p[4]=='\0') {
ival = 1;
return lastst = iconst;
}
 
return 0;
}
/CodeGenerator.c
0,0 → 1,1197
#include <stdio.h>
#include "c.h"
#include "expr.h"
#include "Statement.h"
#include "gen.h"
#include "cglbdec.h"
 
/*
* 68000 C compiler
*
* Copyright 1984, 1985, 1986 Matthew Brandt.
* all commercial rights reserved.
*
* This compiler is intended as an instructive tool for personal use. Any
* use for profit without the written consent of the author is prohibited.
*
* This compiler may be distributed freely for non-commercial use as long
* as this notice stays intact. Please forward any enhancements or questions
* to:
*
* Matthew Brandt
* Box 920337
* Norcross, Ga 30092
*/
 
/*
* this module contains all of the code generation routines
* for evaluating expressions and conditions.
*/
 
/*******************************************************
Modified to support Raptor64 'C64' language
by Robert Finch
robfinch@opencores.org
*******************************************************/
 
AMODE *GenerateExpression(); /* forward ParseSpecifieraration */
 
extern int throwlab;
/*
* construct a reference node for an internal label number.
*/
AMODE *make_label(__int64 lab)
{
struct enode *lnode;
struct amode *ap;
lnode = xalloc(sizeof(struct enode));
lnode->nodetype = en_labcon;
lnode->i = lab;
ap = xalloc(sizeof(struct amode));
ap->mode = am_direct;
ap->offset = lnode;
return ap;
}
 
AMODE *make_string(char *s)
{
ENODE *lnode;
AMODE *ap;
 
lnode = xalloc(sizeof(struct enode));
lnode->nodetype = en_nacon;
lnode->sp = s;
ap = allocAmode();
ap->mode = am_direct;
ap->offset = lnode;
return ap;
}
 
/*
* make a node to reference an immediate value i.
*/
AMODE *make_immed(__int64 i)
{
AMODE *ap;
ENODE *ep;
ep = xalloc(sizeof(struct enode));
ep->nodetype = en_icon;
ep->i = i;
ap = allocAmode();
ap->mode = am_immed;
ap->offset = ep;
return ap;
}
 
AMODE *make_indirect(int i)
{
AMODE *ap;
ENODE *ep;
ep = xalloc(sizeof(struct enode));
ep->nodetype = en_uw_ref;
ep->i = 0;
ap = allocAmode();
ap->mode = am_ind;
ap->preg = i;
ap->offset = ep;
return ap;
}
 
AMODE *make_indexed(__int64 o, int i)
{
AMODE *ap;
ENODE *ep;
ep = xalloc(sizeof(struct enode));
ep->nodetype = en_icon;
ep->i = o;
ap = allocAmode();
ap->mode = am_indx;
ap->preg = i;
ap->offset = ep;
return ap;
}
 
/*
* make a direct reference to a node.
*/
AMODE *make_offset(ENODE *node)
{
AMODE *ap;
ap = allocAmode();
ap->mode = am_direct;
ap->offset = node;
return ap;
}
/*
* MakeLegalAmode will coerce the addressing mode in ap1 into a
* mode that is satisfactory for the flag word.
*/
void MakeLegalAmode(AMODE *ap,int flags, int size)
{
AMODE *ap2;
__int64 i;
 
if (ap==NULL) return;
if( ((flags & F_VOL) == 0) || ap->tempflag )
{
switch( ap->mode ) {
case am_immed:
i = ((ENODE *)(ap->offset))->i;
if (flags & F_IMMED18) {
if (i < 0x1ffff && i > -0x1ffff)
return;
}
else if( flags & F_IMMED )
return; /* mode ok */
break;
case am_reg:
if( flags & F_REG )
return;
break;
case am_ind:
case am_indx:
case am_indx2:
case am_direct:
case am_indx3:
if( flags & F_MEM )
return;
break;
}
}
 
if( flags & F_REG )
{
ReleaseTempRegister(ap); /* maybe we can use it... */
ap2 = GetTempRegister(); /* AllocateRegisterVars to dreg */
if (ap->mode == am_ind || ap->mode==am_indx) {
switch(size) {
case 1: GenerateDiadic(op_lb,0,ap2,ap); break;
case 2: GenerateDiadic(op_lc,0,ap2,ap); break;
case 4: GenerateDiadic(op_lh,0,ap2,ap); break;
case 8: GenerateDiadic(op_lw,0,ap2,ap); break;
}
}
else if (ap->mode==am_immed)
GenerateTriadic(op_ori,0,ap2,makereg(0),ap);
else {
if (ap->mode==am_reg)
GenerateTriadic(op_or,0,ap2,ap,makereg(0));
else {
switch(size) {
case 1: GenerateDiadic(op_lb,0,ap2,ap); break;
case 2: GenerateDiadic(op_lc,0,ap2,ap); break;
case 4: GenerateDiadic(op_lh,0,ap2,ap); break;
case 8: GenerateDiadic(op_lw,0,ap2,ap); break;
}
}
}
ap->mode = am_reg;
ap->preg = ap2->preg;
ap->deep = ap2->deep;
ap->tempflag = 1;
return;
}
if( size == 1 )
{
ReleaseTempRegister(ap);
ap2 = GetTempRegister();
GenerateTriadic(op_or,0,ap2,ap,makereg(0));
GenerateTriadic(op_sext8,0,ap2,ap2,NULL);
ap->mode = ap2->mode;
ap->preg = ap2->preg;
ap->deep = ap2->deep;
size = 2;
}
ap2 = GetTempRegister();
switch(ap->mode) {
case am_ind:
case am_indx:
switch(size) {
case 1: GenerateDiadic(op_lb,0,ap2,ap); break;
case 2: GenerateDiadic(op_lc,0,ap2,ap); break;
case 4: GenerateDiadic(op_lh,0,ap2,ap); break;
case 8: GenerateDiadic(op_lw,0,ap2,ap); break;
}
break;
case am_immed:
GenerateTriadic(op_ori,0,ap2,makereg(0),ap);
case am_reg:
GenerateTriadic(op_or,0,ap2,ap,makereg(0));
default:
switch(size) {
case 1: GenerateDiadic(op_lb,0,ap2,ap); break;
case 2: GenerateDiadic(op_lc,0,ap2,ap); break;
case 4: GenerateDiadic(op_lh,0,ap2,ap); break;
case 8: GenerateDiadic(op_lw,0,ap2,ap); break;
}
}
ap->mode = am_reg;
ap->preg = ap2->preg;
ap->deep = ap2->deep;
ap->tempflag = 1;
}
 
/*
* if isize is not equal to osize then the operand ap will be
* loaded into a register (if not already) and if osize is
* greater than isize it will be extended to match.
*/
void GenerateSignExtend(AMODE *ap, int isize, int osize, int flags)
{
struct amode *ap2;
 
if( isize == osize )
return;
if(ap->mode != am_reg)
MakeLegalAmode(ap,flags & F_REG,isize);
switch( isize )
{
case 1: GenerateDiadic(op_sext8,0,ap,ap); break;
case 2: GenerateDiadic(op_sext16,0,ap,ap); break;
case 4: GenerateDiadic(op_sext32,0,ap,ap); break;
}
}
 
/*
* return true if the node passed can be generated as a short
* offset.
*/
int isshort(ENODE *node)
{
return node->nodetype == en_icon &&
(node->i >= -32768 && node->i <= 32767);
}
 
/*
* return true if the node passed can be evaluated as a byte
* offset.
*/
int isbyte(ENODE *node)
{
return node->nodetype == en_icon &&
(-128 <= node->i && node->i <= 127);
}
 
int ischar(ENODE *node)
{
return node->nodetype == en_icon &&
(node->i >= -32768 && node->i <= 32767);
}
 
/*
* generate code to evaluate an index node (^+) and return
* the addressing mode of the result. This routine takes no
* flags since it always returns either am_ind or am_indx.
*/
AMODE *GenerateIndex(ENODE *node)
{
AMODE *ap1, *ap2, *ap3;
 
if( (node->p[0]->nodetype == en_tempref || node->p[0]->nodetype==en_regvar) && (node->p[1]->nodetype == en_tempref || node->p[1]->nodetype==en_regvar))
{ /* both nodes are registers */
ap1 = GenerateExpression(node->p[0],F_REG,8);
ap2 = GenerateExpression(node->p[1],F_REG,8);
ap1->mode = am_indx2;
ap1->sreg = ap2->preg;
ap1->offset = makeinode(en_icon,0);
return ap1;
}
ap1 = GenerateExpression(node->p[0],F_REG | F_IMMED,8);
if( ap1->mode == am_immed )
{
ap2 = GenerateExpression(node->p[1],F_REG,8);
ap2->mode = am_indx;
ap2->offset = ap1->offset;
ReleaseTempRegister(ap1);
return ap2;
}
ap2 = GenerateExpression(node->p[1],F_ALL,8); /* get right op */
if( ap2->mode == am_immed && ap1->mode == am_reg ) /* make am_indx */
{
ap2->mode = am_indx;
ReleaseTempRegister(ap2);
ap2->preg = ap1->preg;
ap2->deep = ap1->deep;
return ap2;
}
// ap1->mode must be F_REG
MakeLegalAmode(ap2,F_REG,8);
// ap3 = GetTempRegister();
// GenerateTriadic(op_addu,0,ap3,ap1,ap2); /* add left to address reg */
ap1->mode = am_indx2; /* make indirect */
ap1->sreg = ap2->preg;
ap1->offset = makeinode(en_icon,0);
// ReleaseTempRegister(ap2); /* release any temps in ap2 */
// ReleaseTempRegister(ap1);
return ap1; /* return indirect */
}
 
long GetReferenceSize(ENODE *node)
{
switch( node->nodetype ) /* get load size */
{
case en_b_ref:
case en_ub_ref:
case en_bfieldref:
case en_ubfieldref:
return 1;
case en_c_ref:
case en_uc_ref:
case en_cfieldref:
case en_ucfieldref:
return 2;
case en_h_ref:
case en_uh_ref:
case en_hfieldref:
case en_uhfieldref:
return 4;
case en_w_ref:
case en_uw_ref:
case en_wfieldref:
case en_uwfieldref:
case en_tempref:
case en_regvar:
return 8;
}
return 8;
}
 
/*
* return the addressing mode of a dereferenced node.
*/
AMODE *GenerateDereference(ENODE *node,int flags,int size)
{
struct amode *ap1;
int siz1;
 
siz1 = GetReferenceSize(node);
if( node->p[0]->nodetype == en_add )
{
ap1 = GenerateIndex(node->p[0]);
GenerateSignExtend(ap1,siz1,size,flags);
MakeLegalAmode(ap1,flags,size);
return ap1;
}
else if( node->p[0]->nodetype == en_autocon )
{
ap1 = xalloc(sizeof(struct amode));
ap1->mode = am_indx;
ap1->preg = 27;
ap1->offset = makeinode(en_icon,node->p[0]->i);
GenerateSignExtend(ap1,siz1,size,flags);
MakeLegalAmode(ap1,flags,size);
return ap1;
}
ap1 = GenerateExpression(node->p[0],F_REG | F_IMMED,4); /* generate address */
if( ap1->mode == am_reg )
{
ap1->mode = am_ind;
GenerateSignExtend(ap1,siz1,size,flags);
MakeLegalAmode(ap1,flags,size);
return ap1;
}
ap1->mode = am_direct;
GenerateSignExtend(ap1,siz1,size,flags);
MakeLegalAmode(ap1,flags,size);
return ap1;
}
 
void SignExtendBitfield(ENODE *node, struct amode *ap3, __int64 mask)
{
struct amode *ap2;
__int64 umask;
 
umask = 0x8000000000000000L | ~(mask >> 1);
ap2 = GetTempRegister();
GenerateTriadic(op_ori,0,ap2,makereg(0),make_immed(umask));
GenerateTriadic(op_add,0,ap3,ap3,ap2);
GenerateTriadic(op_xor,0,ap3,ap3,ap2);
ReleaseTempRegister(ap2);
}
 
AMODE *GenerateBitfieldDereference(ENODE *node, int flags, int size)
{
AMODE *ap, *ap1,*ap2,*ap3;
long mask,umask;
int width = node->bit_width + 1;
int isSigned;
 
isSigned = node->nodetype==en_wfieldref || node->nodetype==en_hfieldref || node->nodetype==en_cfieldref || node->nodetype==en_bfieldref;
mask = 0;
while (--width) mask = mask + mask + 1;
ap = GenerateDereference(node, flags, node->esize);
MakeLegalAmode(ap, flags, node->esize);
ap3 = GetTempRegister();
GenerateTriadic(op_or,0,ap3,ap,makereg(0));
ReleaseTempRegister(ap);
if (node->bit_offset > 0) {
GenerateDiadic(op_shru, 0, ap3, make_immed((__int64) node->bit_offset));
GenerateDiadic(op_and, 0, ap3, make_immed(mask));
//MakeLegalAmode(ap, flags, node->esize);
if (isSigned)
SignExtendBitfield(node, ap3, mask);
}
else {
GenerateTriadic(op_and, 0, ap3, ap3, make_immed(mask));
if (isSigned)
SignExtendBitfield(node, ap3, mask);
}
//mask = 0;
//while (--width) mask = mask + mask + 1;
// GenerateDiadic(op_and, (int) node->esize, make_immed(mask), ap);
MakeLegalAmode(ap3, flags, node->esize);
return ap3;
}
 
/*
* generate code to evaluate a unary minus or complement.
*/
AMODE *GenerateUnary(ENODE *node,int flags, int size, int op)
{
AMODE *ap,*ap1;
ap = GenerateExpression(node->p[0],F_REG,size);
ap1 = GetTempRegister();
GenerateDiadic(op,0,ap1,ap);
ReleaseTempRegister(ap);
MakeLegalAmode(ap1,flags,size);
return ap1;
}
 
AMODE *GenerateBinary(ENODE *node,int flags, int size, int op)
{
AMODE *ap1, *ap2, *ap3;
int op2;
ap1 = GenerateExpression(node->p[0],F_REG,size);
ap2 = GenerateExpression(node->p[1],F_REG|F_IMMED,size);
ap3 = GetTempRegister();
GenerateTriadic(op,0,ap3,ap1,ap2);
ReleaseTempRegister(ap1);
ReleaseTempRegister(ap2);
MakeLegalAmode(ap3,flags,size);
return ap3;
}
 
/*
* generate code to evaluate a mod operator or a divide
* operator.
*/
AMODE *GenerateModDiv(ENODE *node,int flags,int size, int op)
{
AMODE *ap1, *ap2;
 
if( node->p[0]->nodetype == en_icon )
swap_nodes(node);
ap1 = GenerateExpression(node->p[0],F_REG,8);
ap2 = GenerateExpression(node->p[1],F_REG | F_IMMED,8);
GenerateTriadic(op,0,ap1,ap1,ap2);
GenerateDiadic(op_ext,0,ap1,0);
MakeLegalAmode(ap1,flags,4);
ReleaseTempRegister(ap2);
return ap1;
}
 
/*
* exchange the two operands in a node.
*/
void swap_nodes(ENODE *node)
{
ENODE *temp;
temp = node->p[0];
node->p[0] = node->p[1];
node->p[1] = temp;
}
 
/*
* generate code to evaluate a multiply node. both operands
* are treated as words and the result is long and is always
* in a register so that the 68000 mul instruction can be used.
*/
AMODE *GenerateMultiply(ENODE *node, int flags, int size, int op)
{
AMODE *ap1, *ap2, *ap3;
if( node->p[0]->nodetype == en_icon )
swap_nodes(node);
ap1 = GenerateExpression(node->p[0],F_REG,8);
ap2 = GenerateExpression(node->p[1],F_REG | F_IMMED,8);
ap3 = GetTempRegister();
if (ap2->mode == am_immed) {
if (op==op_mulu)
GenerateTriadic(op_mului,0,ap3,ap1,ap2);
else
GenerateTriadic(op_mulsi,0,ap3,ap1,ap2);
}
else
GenerateTriadic(op,0,ap3,ap1,ap2);
ReleaseTempRegister(ap1);
ReleaseTempRegister(ap2);
MakeLegalAmode(ap3,flags,8);
return ap3;
}
 
/*
* generate code to evaluate a condition operator node (?:)
*/
AMODE *gen_hook(ENODE *node,int flags, int size)
{
AMODE *ap1, *ap2;
int false_label, end_label;
 
false_label = nextlabel++;
end_label = nextlabel++;
flags = (flags & F_REG) | F_VOL;
GenerateFalseJump(node->p[0],false_label);
node = node->p[1];
ap1 = GenerateExpression(node->p[0],flags,size);
ReleaseTempRegister(ap1);
GenerateDiadic(op_bra,0,make_label(end_label),0);
GenerateLabel(false_label);
ap2 = GenerateExpression(node->p[1],flags,size);
if( !equal_address(ap1,ap2) )
{
ReleaseTempRegister(ap2);
// GetTempRegister();
GenerateTriadic(op_or,0,ap1,makereg(0),ap2);
}
GenerateLabel(end_label);
return ap1;
}
 
AMODE *GenerateAssignAdd(ENODE *node,int flags, int size, int op)
{
AMODE *ap1, *ap2, *ap3;
int ssize, mask0, mask1;
ssize = GetNaturalSize(node->p[0]);
if( ssize > size )
size = ssize;
ap1 = GenerateExpression(node->p[0],F_ALL,ssize);
ap2 = GenerateExpression(node->p[1],F_REG | F_IMMED,size);
if (ap2->mode ==am_immed)
switch(op) {
case op_addu: op = op_addui; break;
case op_add: op = op_addui; break;
case op_subu: op = op_subui; break;
case op_sub: op = op_subui; break;
}
if (ap1->mode==am_reg) {
GenerateTriadic(op,0,ap1,ap1,ap2);
}
else {
ap3 = GetTempRegister();
switch(ssize) {
case 1: GenerateDiadic(op_lb,0,ap3,ap1); break;
case 2: GenerateDiadic(op_lc,0,ap3,ap1); break;
case 4: GenerateDiadic(op_lh,0,ap3,ap1); break;
case 8: GenerateDiadic(op_lw,0,ap3,ap1); break;
}
GenerateTriadic(op,0,ap3,ap3,ap2);
switch(ssize) {
case 1: GenerateDiadic(op_sb,0,ap3,ap1); break;
case 2: GenerateDiadic(op_sc,0,ap3,ap1); break;
case 4: GenerateDiadic(op_sh,0,ap3,ap1); break;
case 8: GenerateDiadic(op_sw,0,ap3,ap1); break;
}
ReleaseTempRegister(ap3);
}
ReleaseTempRegister(ap2);
GenerateSignExtend(ap1,ssize,size,flags);
MakeLegalAmode(ap1,flags,size);
return ap1;
}
 
AMODE *GenerateAssignLogic(ENODE *node,int flags, int size, int op)
{
AMODE *ap1, *ap2, *ap3;
int ssize, mask0, mask1;
ssize = GetNaturalSize(node->p[0]);
if( ssize > size )
size = ssize;
ap1 = GenerateExpression(node->p[0],F_ALL,ssize);
ap2 = GenerateExpression(node->p[1],F_REG | F_IMMED,size);
if (ap2->mode==am_immed)
switch(op) {
case op_and: op = op_andi; break;
case op_or: op = op_ori; break;
case op_xor: op = op_xori; break;
}
if (ap1->mode==am_reg) {
GenerateTriadic(op,0,ap1,ap1,ap2);
}
else {
ap3 = GetTempRegister();
switch(ssize) {
case 1: GenerateDiadic(op_lb,0,ap3,ap1); break;
case 2: GenerateDiadic(op_lc,0,ap3,ap1); break;
case 4: GenerateDiadic(op_lh,0,ap3,ap1); break;
case 8: GenerateDiadic(op_lw,0,ap3,ap1); break;
}
GenerateTriadic(op,0,ap3,ap3,ap2);
switch(ssize) {
case 1: GenerateDiadic(op_sb,0,ap3,ap1); break;
case 2: GenerateDiadic(op_sc,0,ap3,ap1); break;
case 4: GenerateDiadic(op_sh,0,ap3,ap1); break;
case 8: GenerateDiadic(op_sw,0,ap3,ap1); break;
}
ReleaseTempRegister(ap3);
}
ReleaseTempRegister(ap2);
GenerateSignExtend(ap1,ssize,size,flags);
MakeLegalAmode(ap1,flags,size);
return ap1;
}
 
/*
* generate a *= node.
*/
AMODE *GenerateAssignMultiply(ENODE *node,int flags, int size, int op)
{
AMODE *ap1, *ap2, *ap3;
int ssize, mask0, mask1;
ssize = GetNaturalSize(node->p[0]);
if( ssize > size )
size = ssize;
ap1 = GenerateExpression(node->p[0],F_ALL,ssize);
ap2 = GenerateExpression(node->p[1],F_REG | F_IMMED,size);
if (ap2->mode==am_immed)
switch(op) {
case op_mulu: op = op_mului; break;
case op_muls: op = op_mulsi; break;
}
if (ap1->mode==am_reg) {
GenerateTriadic(op,0,ap1,ap1,ap2);
}
else {
ap3 = GetTempRegister();
switch(ssize) {
case 1: GenerateDiadic(op_lb,0,ap3,ap1); break;
case 2: GenerateDiadic(op_lc,0,ap3,ap1); break;
case 4: GenerateDiadic(op_lh,0,ap3,ap1); break;
case 8: GenerateDiadic(op_lw,0,ap3,ap1); break;
}
GenerateTriadic(op,0,ap3,ap3,ap2);
switch(ssize) {
case 1: GenerateDiadic(op_sb,0,ap3,ap1); break;
case 2: GenerateDiadic(op_sc,0,ap3,ap1); break;
case 4: GenerateDiadic(op_sh,0,ap3,ap1); break;
case 8: GenerateDiadic(op_sw,0,ap3,ap1); break;
}
ReleaseTempRegister(ap3);
}
ReleaseTempRegister(ap2);
GenerateSignExtend(ap1,ssize,size,flags);
MakeLegalAmode(ap1,flags,size);
return ap1;
}
 
/*
* generate /= and %= nodes.
*/
AMODE *gen_asmodiv(ENODE *node,int flags,int size,int op)
{
AMODE *ap1, *ap2, *ap3;
int siz1;
 
siz1 = GetNaturalSize(node->p[0]);
ap1 = GetTempRegister();
ap2 = GenerateExpression(node->p[0],F_ALL & ~F_IMMED,siz1);
if (ap2->mode==am_reg && ap2->preg != ap1->preg)
GenerateTriadic(op_or,0,ap1,ap2,makereg(0));
else {
switch(siz1) {
case 1: GenerateDiadic(op_lb,0,ap1,ap2); break;
case 2: GenerateDiadic(op_lc,0,ap1,ap2); break;
case 4: GenerateDiadic(op_lh,0,ap1,ap2); break;
case 8: GenerateDiadic(op_lw,0,ap1,ap2); break;
}
}
GenerateSignExtend(ap1,siz1,8,flags);
ap3 = GenerateExpression(node->p[1],F_REG,2);
GenerateTriadic(op,0,ap1,ap1,ap3);
ReleaseTempRegister(ap3);
//GenerateDiadic(op_ext,0,ap1,0);
if (ap2->mode==am_reg)
GenerateTriadic(op_or,0,ap2,ap1,makereg(0));
else
switch(siz1) {
case 1: GenerateDiadic(op_sb,0,ap1,ap2); break;
case 2: GenerateDiadic(op_sc,0,ap1,ap2); break;
case 4: GenerateDiadic(op_sh,0,ap1,ap2); break;
case 8: GenerateDiadic(op_sw,0,ap1,ap2); break;
}
ReleaseTempRegister(ap2);
MakeLegalAmode(ap1,flags,size);
return ap1;
}
 
/*
* generate code for an assignment node. if the size of the
* assignment destination is larger than the size passed then
* everything below this node will be evaluated with the
* assignment size.
*/
AMODE *GenerateAssign(ENODE *node, int flags, int size)
{ struct amode *ap1, *ap2 ,*ap3;
int ssize;
ENODE *ep;
if (node->p[0]->nodetype == en_uwfieldref ||
node->p[0]->nodetype == en_wfieldref ||
node->p[0]->nodetype == en_uhfieldref ||
node->p[0]->nodetype == en_hfieldref ||
node->p[0]->nodetype == en_ucfieldref ||
node->p[0]->nodetype == en_cfieldref ||
node->p[0]->nodetype == en_ubfieldref ||
node->p[0]->nodetype == en_bfieldref) {
long mask;
int i;
/*
* Field assignment
*/
/* get the value */
ap1 = GenerateExpression(node->p[1], F_REG | F_VOL,8);
i = node->p[0]->bit_width;
for (mask = 0; i--; mask = mask + mask + 1);
GenerateDiadic(op_and, 0, make_immed(mask), ap1);
mask <<= node->p[0]->bit_offset;
if (!(flags & F_NOVALUE)) {
/*
* result value needed
*/
ap3 = GetTempRegister();
GenerateTriadic(op_or, 0, ap3, ap1, makereg(0));
} else
ap3 = ap1;
if (node->p[0]->bit_offset > 0) {
if (node->p[0]->bit_offset < 9) {
GenerateTriadic(op_shl, 0, ap3,ap3,make_immed((long) node->p[0]->bit_offset));
}
else {
ap2 = GetTempRegister();
GenerateTriadic(op_ori, 0, ap2,makereg(0),make_immed((long) node->p[0]->bit_offset));
GenerateTriadic(op_shl, 0, ap3, ap3, ap2);
ReleaseTempRegister(ap2);
}
}
ep = makenode(en_w_ref, node->p[0]->p[0], NULL);
ap2 = GenerateExpression(ep, F_MEM,8);
//ap2 = GenerateExpression(node->v.p[0],F_ALL,4);
GenerateTriadic(op_andi, 0, ap2,ap2,make_immed(~mask));
GenerateTriadic(op_or, 0, ap2, ap2, ap3);
ReleaseTempRegister(ap2);
if (!(flags & F_NOVALUE)) {
ReleaseTempRegister(ap3);
}
MakeLegalAmode(ap1, flags, size);
return ap1;
}
 
ssize = GetReferenceSize(node->p[0]);
if( ssize > size )
size = ssize;
ap2 = GenerateExpression(node->p[1],F_REG,size);
ap1 = GenerateExpression(node->p[0],F_ALL,ssize);
if (ap1->mode == am_reg) {
GenerateDiadic(op_mov,0,ap1,ap2);
}
else {
switch(size) {
case 1: GenerateDiadic(op_sb,0,ap2,ap1); break;
case 2: GenerateDiadic(op_sc,0,ap2,ap1); break;
case 4: GenerateDiadic(op_sh,0,ap2,ap1); break;
case 8: GenerateDiadic(op_sw,0,ap2,ap1); break;
}
}
ReleaseTempRegister(ap1);
return ap2;
}
 
/*
* generate an auto increment or decrement node. op should be
* either op_add (for increment) or op_sub (for decrement).
*/
AMODE *GenerateAutoIncrement(ENODE *node,int flags,int size,int op)
{
AMODE *ap1, *ap2;
int siz1;
 
siz1 = GetNaturalSize(node->p[0]);
if( flags & F_NOVALUE ) /* dont need result */
{
ap1 = GenerateExpression(node->p[0],F_ALL,siz1);
switch(op) {
case op_addu: op = op_addui; break;
case op_add: op = op_addui; break;
case op_subu: op = op_subui; break;
case op_sub: op = op_subui; break;
}
if (ap1->mode != am_reg) {
ap2 = GetTempRegister();
switch(size) {
case 1: GenerateTriadic(op_lb,0,ap2,ap1,NULL); break;
case 2: GenerateTriadic(op_lc,0,ap2,ap1,NULL); break;
case 4: GenerateTriadic(op_lh,0,ap2,ap1,NULL); break;
case 8: GenerateTriadic(op_lw,0,ap2,ap1,NULL); break;
}
GenerateTriadic(op,0,ap2,ap2,make_immed(node->i));
switch(size) {
case 1: GenerateTriadic(op_sb,0,ap2,ap1,NULL); break;
case 2: GenerateTriadic(op_sc,0,ap2,ap1,NULL); break;
case 4: GenerateTriadic(op_sh,0,ap2,ap1,NULL); break;
case 8: GenerateTriadic(op_sw,0,ap2,ap1,NULL); break;
}
ReleaseTempRegister(ap2);
}
else
GenerateTriadic(op,0,ap1,ap1,make_immed(node->i));
ReleaseTempRegister(ap1);
return ap1;
}
ap2 = GenerateExpression(node->p[0],F_ALL,siz1);
if (ap2->mode == am_reg) {
GenerateTriadic(op,0,ap2,ap2,make_immed(node->i));
return ap2;
}
else {
ap1 = GetTempRegister();
switch(siz1) {
case 1: GenerateDiadic(op_lb,0,ap1,ap2); break;
case 2: GenerateDiadic(op_lc,0,ap1,ap2); break;
case 4: GenerateDiadic(op_lh,0,ap1,ap2); break;
case 8: GenerateDiadic(op_lw,0,ap1,ap2); break;
}
switch(op) {
case op_addu: op = op_addui; break;
case op_add: op = op_addui; break;
case op_subu: op = op_subui; break;
case op_sub: op = op_subui; break;
}
GenerateTriadic(op,0,ap1,ap1,make_immed(node->i));
switch(siz1) {
case 1: GenerateDiadic(op_sb,0,ap1,ap2); break;
case 2: GenerateDiadic(op_sc,0,ap1,ap2); break;
case 4: GenerateDiadic(op_sh,0,ap1,ap2); break;
case 8: GenerateDiadic(op_sw,0,ap1,ap2); break;
}
}
ReleaseTempRegister(ap2);
GenerateSignExtend(ap1,siz1,size,flags);
return ap1;
}
 
/*
* general expression evaluation. returns the addressing mode
* of the result.
*/
AMODE *GenerateExpression(ENODE *node, int flags, int size)
{
AMODE *ap1, *ap2;
int lab0, lab1;
int natsize;
 
if( node == NULL )
{
printf("DIAG - null node in GenerateExpression.\n");
return NULL;
}
switch( node->nodetype )
{
case en_icon:
case en_labcon:
case en_nacon:
ap1 = allocAmode();
ap1->mode = am_immed;
ap1->offset = node;
MakeLegalAmode(ap1,flags,size);
return ap1;
case en_autocon:
ap1 = GetTempRegister();
ap2 = allocAmode();
ap2->mode = am_indx;
ap2->preg = 27; /* frame pointer */
ap2->offset = node; /* use as constant node */
GenerateDiadic(op_lea,0,ap1,ap2);
MakeLegalAmode(ap1,flags,size);
return ap1; /* return reg */
case en_b_ref:
case en_c_ref:
case en_h_ref:
case en_ub_ref:
case en_uc_ref:
case en_uh_ref:
case en_w_ref:
case en_uw_ref:
return GenerateDereference(node,flags,size);
case en_uwfieldref:
case en_wfieldref:
case en_bfieldref:
case en_ubfieldref:
case en_cfieldref:
case en_ucfieldref:
case en_hfieldref:
case en_uhfieldref:
return GenerateBitfieldDereference(node,flags,size);
case en_regvar:
case en_tempref:
ap1 = xalloc(sizeof(struct amode));
ap1->mode = am_reg;
ap1->preg = node->i;
ap1->tempflag = 0; /* not a temporary */
MakeLegalAmode(ap1,flags,size);
return ap1;
case en_uminus: return GenerateUnary(node,flags,size,op_neg);
case en_compl: return GenerateUnary(node,flags,size,op_not);
case en_add: return GenerateBinary(node,flags,size,op_add);
case en_sub: return GenerateBinary(node,flags,size,op_sub);
case en_and: return GenerateBinary(node,flags,size,op_and);
case en_or: return GenerateBinary(node,flags,size,op_or);
case en_xor: return GenerateBinary(node,flags,size,op_xor);
case en_mul: return GenerateMultiply(node,flags,size,op_muls);
case en_mulu: return GenerateMultiply(node,flags,size,op_mulu);
case en_div: return GenerateModDiv(node,flags,size,op_divs);
case en_udiv: return GenerateModDiv(node,flags,size,op_divu);
case en_mod: return GenerateModDiv(node,flags,size,op_mod);
case en_umod: return GenerateModDiv(node,flags,size,op_modu);
case en_shl: return GenerateShift(node,flags,size,op_shl);
case en_shr: return GenerateShift(node,flags,size,op_shr);
case en_shru: return GenerateShift(node,flags,size,op_shru);
case en_asadd: return GenerateAssignAdd(node,flags,size,op_add);
case en_assub: return GenerateAssignAdd(node,flags,size,op_sub);
case en_asand: return GenerateAssignLogic(node,flags,size,op_and);
case en_asor: return GenerateAssignLogic(node,flags,size,op_or);
case en_asxor: return GenerateAssignLogic(node,flags,size,op_xor);
case en_aslsh:
return GenerateAssignShift(node,flags,size,op_shl);
case en_asrsh:
return GenerateAssignShift(node,flags,size,op_shr);
case en_asmul: return GenerateAssignMultiply(node,flags,size,op_muls);
case en_asmulu: return GenerateAssignMultiply(node,flags,size,op_mulu);
case en_asdiv:
return gen_asmodiv(node,flags,size,op_divs);
case en_asmod:
return gen_asmodiv(node,flags,size,op_muls);
case en_assign:
return GenerateAssign(node,flags,size);
case en_ainc:
return GenerateAutoIncrement(node,flags,size,op_add);
case en_adec:
return GenerateAutoIncrement(node,flags,size,op_sub);
case en_land: case en_lor:
case en_eq: case en_ne:
case en_lt: case en_le:
case en_gt: case en_ge:
case en_ult: case en_ule:
case en_ugt: case en_uge:
case en_not:
lab0 = nextlabel++;
lab1 = nextlabel++;
GenerateFalseJump(node,lab0);
ap1 = GetTempRegister();
GenerateTriadic(op_ori,0,ap1,makereg(0),make_immed(1));
GenerateTriadic(op_bra,0,make_label(lab1),NULL,NULL);
GenerateLabel(lab0);
GenerateTriadic(op_ori,0,ap1,makereg(0),make_immed(0));
GenerateLabel(lab1);
return ap1;
case en_cond:
return gen_hook(node,flags,size);
case en_void:
natsize = GetNaturalSize(node->p[0]);
ReleaseTempRegister(GenerateExpression(node->p[0],F_ALL | F_NOVALUE,natsize));
return GenerateExpression(node->p[1],flags,size);
case en_fcall:
return GenerateFunctionCall(node,flags);
default:
printf("DIAG - uncoded node in GenerateExpression.\n");
return 0;
}
}
 
/*
* return the natural evaluation size of a node.
*/
int GetNaturalSize(ENODE *node)
{
int siz0, siz1;
if( node == NULL )
return 0;
switch( node->nodetype )
{
case en_uwfieldref:
case en_wfieldref:
return 8;
case en_bfieldref:
case en_ubfieldref:
return 1;
case en_cfieldref:
case en_ucfieldref:
return 2;
case en_hfieldref:
case en_uhfieldref:
return 4;
case en_icon:
if( -128 <= node->i && node->i <= 127 )
return 1;
if( -32768 <= node->i && node->i <= 32767 )
return 2;
if (-2147483648L <= node->i && node->i <= 2147483647L)
return 4;
return 8;
case en_fcall: case en_labcon:
case en_nacon: case en_autocon:
case en_tempref:
case en_regvar:
case en_cbw:
case en_ccw:
case en_chw:
return 8;
case en_b_ref:
case en_ub_ref:
return 1;
case en_cbc:
case en_c_ref: return 2;
case en_uc_ref: return 2;
case en_cbh: return 4;
case en_cch: return 4;
case en_h_ref: return 4;
case en_uh_ref: return 4;
case en_w_ref: case en_uw_ref:
return 8;
case en_not: case en_compl:
case en_uminus: case en_assign:
case en_ainc: case en_adec:
return GetNaturalSize(node->p[0]);
case en_add: case en_sub:
case en_mul: case en_div:
case en_mod: case en_and:
case en_or: case en_xor:
case en_shl: case en_shr: case en_shru:
case en_eq: case en_ne:
case en_lt: case en_le:
case en_gt: case en_ge:
case en_ult: case en_ule:
case en_ugt: case en_uge:
case en_land: case en_lor:
case en_asadd: case en_assub:
case en_asmul: case en_asdiv:
case en_asmod: case en_asand:
case en_asor: case en_asxor: case en_aslsh:
case en_asrsh:
siz0 = GetNaturalSize(node->p[0]);
siz1 = GetNaturalSize(node->p[1]);
if( siz1 > siz0 )
return siz1;
else
return siz0;
case en_void: case en_cond:
return GetNaturalSize(node->p[1]);
default:
printf("DIAG - natural size error %d.\n", node->nodetype);
break;
}
return 0;
}
 
 
void gen_b(ENODE *node, int op, int label)
{
int size;
struct amode *ap1, *ap2;
 
size = GetNaturalSize(node);
ap1 = GenerateExpression(node->p[0],F_REG, size);
ap2 = GenerateExpression(node->p[1],F_REG|F_IMMED18,size);
GenerateTriadic(op,0,ap1,ap2,make_label(label));
ReleaseTempRegister(ap2);
ReleaseTempRegister(ap1);
}
/*
* generate a jump to label if the node passed evaluates to
* a true condition.
*/
void GenerateTrueJump(ENODE *node, int label)
{ AMODE *ap1,*ap2;
int siz1;
int lab0;
int size;
if( node == 0 )
return;
switch( node->nodetype )
{
case en_eq: gen_b(node, op_beq, label); break;
case en_ne: gen_b(node, op_bne, label); break;
case en_lt: gen_b(node, op_blt, label); break;
case en_le: gen_b(node, op_ble, label); break;
case en_gt: gen_b(node, op_bgt, label); break;
case en_ge: gen_b(node, op_bge, label); break;
case en_ult: gen_b(node, op_bltu, label); break;
case en_ule: gen_b(node, op_bleu, label); break;
case en_ugt: gen_b(node, op_bgtu, label); break;
case en_uge: gen_b(node, op_bgeu, label); break;
case en_land:
lab0 = nextlabel++;
GenerateFalseJump(node->p[0],lab0);
GenerateTrueJump(node->p[1],label);
GenerateLabel(lab0);
break;
case en_lor:
GenerateTrueJump(node->p[0],label);
GenerateTrueJump(node->p[1],label);
break;
case en_not:
GenerateFalseJump(node->p[0],label);
break;
default:
siz1 = GetNaturalSize(node);
ap1 = GenerateExpression(node,F_REG,siz1);
// GenerateDiadic(op_tst,siz1,ap1,0);
ReleaseTempRegister(ap1);
GenerateTriadic(op_bne,0,ap1,makereg(0),make_label(label));
break;
}
}
 
/*
* generate code to execute a jump to label if the expression
* passed is false.
*/
void GenerateFalseJump(ENODE *node,int label)
{
AMODE *ap,*ap1,*ap2;
int size;
int siz1;
int lab0;
if( node == NULL )
return;
switch( node->nodetype )
{
case en_eq: gen_b(node, op_bne, label); break;
case en_ne: gen_b(node, op_beq, label); break;
case en_lt: gen_b(node, op_bge, label); break;
case en_le: gen_b(node, op_bgt, label); break;
case en_gt: gen_b(node, op_ble, label); break;
case en_ge: gen_b(node, op_blt, label); break;
case en_ult: gen_b(node, op_bgeu, label); break;
case en_ule: gen_b(node, op_bgtu, label); break;
case en_ugt: gen_b(node, op_bleu, label); break;
case en_uge: gen_b(node, op_bltu, label); break;
case en_land:
GenerateFalseJump(node->p[0],label);
GenerateFalseJump(node->p[1],label);
break;
case en_lor:
lab0 = nextlabel++;
GenerateTrueJump(node->p[0],lab0);
GenerateFalseJump(node->p[1],label);
GenerateLabel(lab0);
break;
case en_not:
GenerateTrueJump(node->p[0],label);
break;
default:
siz1 = GetNaturalSize(node);
ap = GenerateExpression(node,F_REG,siz1);
// GenerateDiadic(op_tst,siz1,ap,0);
ReleaseTempRegister(ap);
GenerateTriadic(op_beq,0,ap,makereg(0),make_label(label));
break;
}
}
/ParseStatements.c
0,0 → 1,735
// ============================================================================
// (C) 2012 Robert Finch
// All Rights Reserved.
// robfinch<remove>@opencores.org
//
// C64 - Raptor64 'C' derived language compiler
// - 64 bit CPU
//
// This source file is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file 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 this program. If not, see <http://www.gnu.org/licenses/>.
//
// ============================================================================
//
#include <stdio.h>
#include "c.h"
#include "expr.h"
#include "Statement.h"
#include "gen.h"
#include "cglbdec.h"
 
extern TYP *head, *tail;
extern char *declid;
extern int catchdecl;
Statement *ParseStatement(); /* forward declararation */
Statement *ParseCatchStatement();
Statement *NewStatement(int typ, int gt) {
Statement *s = (Statement *)xalloc(sizeof(Statement));
s->stype = typ;
if (gt) NextToken();
return s;
};
 
 
int GetTypeHash(TYP *p)
{
int n;
TYP *p1;
 
n = 0;
do {
if (p->type==bt_pointer)
n+=20000;
p1 = p;
p = p->btp;
} while (p);
n += p1->typeno;
return n;
}
 
 
//struct snode *interrupt_stmt()
//{ struct snode *snp;
// SYM *sp;
// TYP *temp1;
//
// NextToken();
// if( lastst != id ) {
// error(ERR_IDEXPECT);
// return 0;
// }
// sp = allocSYM();
// sp->name = litlate(lastid);
// sp->value.i = nextlabel++;
// sp->storage_class = sc_global;
// sp->tp = temp1;
// temp1 = maketype(bt_long,0);
// temp1->val_flag = 1;
// insert(sp,&lsyms);
// NextToken(); /* get past label name */
// needpunc( colon );
// snp = (struct snode *)xalloc(sizeof(struct snode));
// snp->stype = st_interrupt;
// snp->label = sp->name;
// snp->next = 0;
// snp->s1 = statement();
// return snp;
//}
//
struct snode *vortex_stmt()
{ struct snode *snp;
SYM *sp;
TYP *temp1;
 
NextToken();
if( lastst != id ) {
error(ERR_IDEXPECT);
return 0;
}
temp1 = maketype(bt_long,0);
temp1->val_flag = 1;
sp = allocSYM();
sp->name = litlate(lastid);
sp->value.i = nextlabel++;
sp->storage_class = sc_global;
sp->tp = temp1;
insert(sp,&lsyms);
NextToken(); /* get past label name */
needpunc( colon );
snp = (struct snode *)xalloc(sizeof(struct snode));
snp->stype = st_vortex;
snp->label = sp->name;
snp->next = 0;
snp->s1 = ParseStatement();
return snp;
}
Statement *ParseWhileStatement()
{
Statement *snp;
 
snp = NewStatement(st_while, TRUE);
if( lastst != openpa )
error(ERR_EXPREXPECT);
else {
NextToken();
if( expression(&(snp->exp)) == 0 )
error(ERR_EXPREXPECT);
needpunc( closepa );
if (lastst==kw_do)
NextToken();
snp->s1 = ParseStatement();
}
return snp;
}
Statement *ParseUntilStatement()
{
Statement *snp;
snp = NewStatement(st_until, TRUE);
if( lastst != openpa )
error(ERR_EXPREXPECT);
else {
NextToken();
if( expression(&(snp->exp)) == 0 )
error(ERR_EXPREXPECT);
needpunc( closepa );
snp->s1 = ParseStatement();
}
return snp;
}
Statement *ParseDoStatement()
{
Statement *snp;
snp = NewStatement(st_do, TRUE);
snp->s1 = ParseStatement();
if (lastst == kw_until)
snp->stype = st_dountil;
else if (lastst== kw_loop)
snp->stype = st_doloop;
if( lastst != kw_while && lastst != kw_until && lastst != kw_loop )
error(ERR_WHILEXPECT);
else {
NextToken();
if (snp->stype!=st_doloop) {
if( expression(&(snp->exp)) == 0 )
error(ERR_EXPREXPECT);
}
if( lastst != end )
needpunc( semicolon );
}
return snp;
}
Statement *ParseForStatement()
{
Statement *snp;
snp = NewStatement(st_for, TRUE);
needpunc(openpa);
if( expression(&(snp->initExpr)) == NULL )
snp->initExpr = NULL;
needpunc(semicolon);
if( expression(&(snp->exp)) == NULL )
snp->exp = NULL;
needpunc(semicolon);
if( expression(&(snp->incrExpr)) == NULL )
snp->incrExpr = NULL;
needpunc(closepa);
snp->s1 = ParseStatement();
return snp;
}
Statement *ParseForeverStatement()
{
Statement *snp;
snp = NewStatement(st_forever, TRUE);
snp->stype = st_forever;
snp->s1 = ParseStatement();
return snp;
}
 
struct snode *ParseCriticalStatement()
{
struct snode *snp;
SYM *sp;
snp = (struct snode*)xalloc(sizeof(struct snode));
NextToken();
if (lastst==openpa)
NextToken();
if( lastst != id ) {
error(ERR_IDEXPECT);
return 0;
}
if( (sp = search(lastid,&gsyms[0])) == NULL ) {
error( ERR_UNDEFINED );
return 0;
}
NextToken();
if (lastst==closepa)
NextToken();
snp->stype = st_critical;
snp->label = sp->name;
snp->next = 0;
snp->s1 = ParseStatement();
return snp;
}
Statement *ParseSpinlockStatement()
{
Statement *snp;
SYM *sp;
 
snp = NewStatement(st_spinlock, TRUE);
if (lastst==openpa)
NextToken();
if( lastst != id ) {
error(ERR_IDEXPECT);
return 0;
}
if( (sp = search(lastid,&gsyms[0])) == NULL ) {
error( ERR_UNDEFINED );
return 0;
}
NextToken();
if (lastst==comma) {
NextToken();
snp->exp = GetIntegerExpression();
}
if (lastst==closepa)
NextToken();
snp->label = sp->name;
snp->next = 0;
snp->s1 = ParseStatement();
if (lastst==kw_lockfail) {
NextToken();
snp->s2 = ParseStatement();
}
return snp;
}
Statement *ParseSpinunlockStatement()
{
Statement *snp;
SYM *sp;
 
snp = NewStatement(st_spinunlock, TRUE);
if (lastst==openpa)
NextToken();
if( lastst != id ) {
error(ERR_IDEXPECT);
return 0;
}
if( (sp = search(lastid,&gsyms[0])) == NULL ) {
error( ERR_UNDEFINED );
return 0;
}
NextToken();
if (lastst==closepa)
NextToken();
snp->label = sp->name;
snp->next = 0;
return snp;
}
Statement *ParseFirstcallStatement()
{
Statement *snp;
snp = NewStatement(st_firstcall, TRUE);
snp->s1 = ParseStatement();
return snp;
}
Statement *ParseIfStatement()
{
Statement *snp;
 
snp = NewStatement(st_if, TRUE);
if( lastst != openpa )
error(ERR_EXPREXPECT);
else {
NextToken();
if( expression(&(snp->exp)) == 0 )
error(ERR_EXPREXPECT);
needpunc( closepa );
if (lastst==kw_then)
NextToken();
snp->s1 = ParseStatement();
if( lastst == kw_else ) {
NextToken();
snp->s2 = ParseStatement();
}
else if (lastst == kw_elsif) {
snp->s2 = ParseIfStatement();
}
else
snp->s2 = 0;
}
return snp;
}
 
Statement *ParseCatchStatement()
{
Statement *snp;
SYM *sp;
TYP *tp,*tp1,*tp2;
 
snp = NewStatement(st_catch, TRUE);
if (lastst != openpa) {
snp->label = NULL;
snp->s2 = 99999;
snp->s1 = ParseStatement();
return snp;
}
needpunc(openpa);
tp = head;
tp1 = tail;
catchdecl = TRUE;
ParseAutoDeclarations();
catchdecl = FALSE;
tp2 = head;
head = tp;
tail = tp1;
needpunc(closepa);
 
if( (sp = search(declid,&lsyms)) == NULL)
sp = makeint(declid);
snp->s1 = ParseStatement();
snp->label = (char *)sp; // save off symbol pointer
if (sp->tp->typeno >= bt_last)
error(ERR_CATCHSTRUCT);
snp->s2 = GetTypeHash(sp->tp);
return snp;
}
 
Statement *ParseCaseStatement()
{
Statement *snp;
Statement *head, *tail;
int buf[256];
int nn;
int *bf;
 
snp = NewStatement(st_case, FALSE);
if (lastst == kw_fallthru) // ignore "fallthru"
NextToken();
if( lastst == kw_case ) {
NextToken();
snp->s2 = 0;
nn = 0;
do {
buf[nn] = GetIntegerExpression();
nn++;
if (lastst != comma)
break;
NextToken();
} while (nn < 256);
if (nn==256)
error(ERR_TOOMANYCASECONSTANTS);
bf = (int *)xalloc(sizeof(int)*(nn+1));
bf[0] = nn;
for (; nn > 0; nn--)
bf[nn]=buf[nn-1];
snp->label = bf;
}
else if( lastst == kw_default) {
NextToken();
snp->s2 = 1;
snp->stype = st_default;
}
else {
error(ERR_NOCASE);
return NULL;
}
needpunc(colon);
head = NULL;
while( lastst != end && lastst != kw_case && lastst != kw_default ) {
if( head == NULL )
head = tail = ParseStatement();
else {
tail->next = ParseStatement();
if( tail->next != NULL )
tail = tail->next;
}
tail->next = 0;
}
snp->s1 = head;
return snp;
}
int CheckForDuplicateCases(Statement *head)
{
Statement *top, *cur;
 
cur = top = head;
while( top != NULL )
{
cur = top->next;
while( cur != NULL )
{
if( (!(cur->s1 || cur->s2) && cur->label == top->label)
|| (cur->s2 && top->s2) )
{
printf(" duplicate case value %d\n",cur->label);
return TRUE;
}
cur = cur->next;
}
top = top->next;
}
return FALSE;
}
Statement *ParseSwitchStatement()
{
Statement *snp;
Statement *head, *tail;
 
snp = NewStatement(st_switch, TRUE);
if( expression(&(snp->exp)) == NULL )
error(ERR_EXPREXPECT);
needpunc(begin);
head = 0;
while( lastst != end ) {
if( head == NULL )
head = tail = ParseCaseStatement();
else {
tail->next = ParseCaseStatement();
if( tail->next != NULL )
tail = tail->next;
}
if (tail==NULL) break; // end of file in switch
tail->next = NULL;
}
snp->s1 = head;
NextToken();
if( CheckForDuplicateCases(head) )
error(ERR_DUPCASE);
return snp;
}
Statement *ParseReturnStatement()
{
Statement *snp;
 
snp = NewStatement(st_return, TRUE);
expression(&(snp->exp));
if( lastst != end )
needpunc( semicolon );
return snp;
}
Statement *ParseThrowStatement()
{
Statement *snp;
TYP *tp;
 
currentFn->DoesThrow = TRUE;
snp = NewStatement(st_throw, TRUE);
tp = expression(&(snp->exp));
snp->label = GetTypeHash(tp);
if( lastst != end )
needpunc( semicolon );
return snp;
}
Statement *ParseBreakStatement()
{
Statement *snp;
 
snp = NewStatement(st_break, TRUE);
if( lastst != end )
needpunc( semicolon );
return snp;
}
Statement *ParseContinueStatement()
{
Statement *snp;
 
snp = NewStatement(st_continue, TRUE);
if( lastst != end )
needpunc( semicolon );
return snp;
}
Statement *ParseIntoffStatement()
{
Statement *snp;
snp = NewStatement(st_intoff, TRUE);
if( lastst != end )
needpunc( semicolon );
return snp;
}
Statement *ParseIntonStatement()
{
Statement *snp;
 
snp = NewStatement(st_inton, TRUE);
if( lastst != end )
needpunc( semicolon );
return snp;
}
Statement *ParseStopStatement()
{
Statement *snp;
 
snp = NewStatement(st_stop, TRUE);
if( lastst != end )
needpunc( semicolon );
return snp;
}
Statement *ParseAsmStatement()
{
static char buf[2001];
int nn;
 
Statement *snp;
snp = NewStatement(st_asm, FALSE);
while( isspace(lastch) )
getch();
NextToken();
if (lastst != begin)
error(ERR_PUNCT);
nn = 0;
do {
getch();
if (lastch=='}')
break;
buf[nn++] = lastch;
}
while(lastch!=-1 && nn < 2000);
if (nn >= 2000)
error(ERR_ASMTOOLONG);
buf[nn] = '\0';
snp->label = litlate(buf);
return snp;
}
 
Statement *ParseTryStatement()
{
Statement *snp;
TYP *tp,*tp1,*tp2;
SYM *sp;
Statement *hd, *tl;
 
hd = NULL;
tl = NULL;
snp = NewStatement(st_try, TRUE);
snp->s1 = ParseStatement();
if (lastst != kw_catch)
error(ERR_CATCHEXPECT);
while( lastst == kw_catch ) {
if( hd == NULL )
hd = tl = ParseCatchStatement();
else {
tl->next = ParseCatchStatement();
if( tl->next != NULL )
tl = tl->next;
}
if (tl==NULL) break; // end of file in try
tl->next = NULL;
}
snp->s2 = hd;
return snp;
}
Statement *ParseExpressionStatement()
{
Statement *snp;
snp = NewStatement(st_expr, FALSE);
if( expression(&(snp->exp)) == NULL ) {
error(ERR_EXPREXPECT);
NextToken();
}
if( lastst != end )
needpunc( semicolon );
return snp;
}
Statement *ParseCompoundStatement()
{
Statement *head, *tail;
 
head = 0;
while( lastst != end ) {
if( head == NULL )
head = tail = ParseStatement();
else {
tail->next = ParseStatement();
if( tail->next != NULL )
tail = tail->next;
}
}
NextToken();
return head;
}
Statement *ParseLabelStatement()
{
Statement *snp;
SYM *sp;
 
snp = NewStatement(st_label, FALSE);
if( (sp = search(lastid,&lsyms)) == NULL ) {
sp = allocSYM();
sp->name = litlate(lastid);
sp->storage_class = sc_label;
sp->tp = 0;
sp->value.i = nextlabel++;
insert(sp,&lsyms);
}
else {
if( sp->storage_class != sc_ulabel )
error(ERR_LABEL);
else
sp->storage_class = sc_label;
}
NextToken(); /* get past id */
needpunc(colon);
if( sp->storage_class == sc_label ) {
snp->label = sp->value.i;
snp->next = NULL;
return snp;
}
return 0;
}
Statement *ParseGotoStatement()
{
Statement *snp;
SYM *sp;
 
NextToken();
if( lastst != id ) {
error(ERR_IDEXPECT);
return NULL;
}
snp = NewStatement(st_goto, FALSE);
if( (sp = search(lastid,&lsyms)) == NULL ) {
sp = allocSYM();
sp->name = litlate(lastid);
sp->value.i = nextlabel++;
sp->storage_class = sc_ulabel;
sp->tp = 0;
insert(sp,&lsyms);
}
NextToken(); /* get past label name */
if( lastst != end )
needpunc( semicolon );
if( sp->storage_class != sc_label && sp->storage_class != sc_ulabel)
error( ERR_LABEL );
else {
snp->stype = st_goto;
snp->label = sp->value.i;
snp->next = NULL;
return snp;
}
return NULL;
}
Statement *ParseStatement()
{
Statement *snp;
switch( lastst ) {
case semicolon:
NextToken();
snp = NULL;
break;
case begin:
NextToken();
snp = ParseCompoundStatement();
return snp;
case kw_if: snp = ParseIfStatement(); break;
case kw_while: snp = ParseWhileStatement(); break;
case kw_until: snp = ParseUntilStatement(); break;
case kw_for: snp = ParseForStatement(); break;
case kw_forever: snp = ParseForeverStatement(); break;
case kw_firstcall: snp = ParseFirstcallStatement(); break;
case kw_return: snp = ParseReturnStatement(); break;
case kw_break: snp = ParseBreakStatement(); break;
case kw_goto: snp = ParseGotoStatement(); break;
case kw_continue: snp = ParseContinueStatement(); break;
case kw_do:
case kw_loop: snp = ParseDoStatement(); break;
case kw_switch: snp = ParseSwitchStatement(); break;
case kw_try: snp = ParseTryStatement(); break;
case kw_throw: snp = ParseThrowStatement(); break;
case kw_vortex:
snp = vortex_stmt();
break;
case kw_intoff: snp = ParseIntoffStatement(); break;
case kw_inton: snp = ParseIntonStatement(); break;
case kw_stop: snp = ParseStopStatement(); break;
case kw_asm:
snp = ParseAsmStatement(); break;
case kw_critical: snp = ParseCriticalStatement(); break;
case kw_spinlock: snp = ParseSpinlockStatement(); break;
case kw_spinunlock: snp = ParseSpinunlockStatement(); break;
case id:
SkipSpaces();
if( lastch == ':' )
return ParseLabelStatement();
// else fall through to parse expression
default:
snp = ParseExpressionStatement();
break;
}
if( snp != NULL )
snp->next = NULL;
return snp;
}
/Register.c
0,0 → 1,132
// ============================================================================
// (C) 2012 Robert Finch
// All Rights Reserved.
// robfinch<remove>@opencores.org
//
// C64 - Raptor64 'C' derived language compiler
// - 64 bit CPU
//
// This source file is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file 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 this program. If not, see <http://www.gnu.org/licenses/>.
//
// ============================================================================
//
#include <stdio.h>
#include "c.h"
#include "expr.h"
#include "Statement.h"
#include "gen.h"
#include "cglbdec.h"
 
int tmpregs[] = {3,4,5,6,7,8,9,10};
int regstack[8];
int rsp=7;
int regmask=0;
 
void initRegStack()
{
for (rsp=0; rsp < 8; rsp=rsp+1)
regstack[rsp] = tmpregs[rsp];
rsp = 0;
}
 
void GenerateTempRegPush(int reg, int rmode)
{
AMODE *ap1;
ap1 = allocAmode();
ap1->preg = reg;
ap1->mode = rmode;
GenerateTriadic(op_subui,0,makereg(30),makereg(30),make_immed(8));
GenerateTriadic(op_sw,0,ap1,make_indirect(30),NULL);
}
 
void GenerateTempRegPop(int reg, int rmode)
{
AMODE *ap1;
ap1 = allocAmode();
ap1->preg = reg;
ap1->mode = rmode;
GenerateTriadic(op_lw,0,ap1,make_indirect(30),NULL);
GenerateTriadic(op_addui,0,makereg(30),makereg(30),make_immed(8));
}
 
void initstack()
{
initRegStack();
}
 
AMODE *GetTempRegister()
{
AMODE *ap;
ap = allocAmode();
ap->mode = am_reg;
ap->preg = PopFromRstk();
ap->deep = rsp;
return ap;
}
 
int PopFromRstk()
{
int reg = 0;
 
if (rsp < 8) {
reg = regstack[rsp];
rsp = rsp + 1;
regmask |= (1 << (reg));
}
else
error(ERR_EXPRTOOCOMPLEX);
return reg;
}
 
void PushOnRstk(int reg)
{
if (rsp > 0) {
rsp = rsp - 1;
regstack[rsp] = reg;
regmask &= ~(1 << (reg));
}
else
printf("DIAG - register stack underflow.\r\n");
}
 
int SaveTempRegs()
{
if (regmask != 0) {
GenerateTriadic(op_subui,0,makereg(30),makereg(30),make_immed(popcnt(regmask)*8));
GenerateTriadic(op_sm,0,make_indirect(30),make_mask(regmask),NULL);
}
return regmask;
}
 
void RestoreTempRegs(int rgmask)
{
if (rgmask != 0) {
GenerateTriadic(op_lm,0,make_indirect(30),make_mask(rgmask),NULL);
GenerateTriadic(op_addui,0,makereg(30),makereg(30),make_immed(popcnt(rgmask)*8));
}
}
 
void ReleaseTempRegister(struct amode *ap)
{
if (ap==NULL) {
printf("DIAG - NULL pointer in ReleaseTempRegister\r\n");
return;
}
if( ap->mode == am_immed || ap->mode == am_direct )
return; // no registers used
if(ap->preg < 11 && ap->preg >= 3)
PushOnRstk(ap->preg);
}
 
 
/ParseStructDeclaration.c
0,0 → 1,106
#include <stdio.h>
#include <string.h>
#include "c.h"
#include "expr.h"
#include "Statement.h"
#include "gen.h"
#include "cglbdec.h"
 
/*
* 68000 C compiler
*
* Copyright 1984, 1985, 1986 Matthew Brandt.
* all commercial rights reserved.
*
* This compiler is intended as an instructive tool for personal use. Any
* use for profit without the written consent of the author is prohibited.
*
* This compiler may be distributed freely for non-commercial use as long
* as this notice stays intact. Please forward any enhancements or questions
* to:
*
* Matthew Brandt
* Box 920337
* Norcross, Ga 30092
*/
/*******************************************************
Copyright 2012 Robert Finch
Modified to support Raptor64 'C64' language
by Robert Finch
robfinch@opencores.org
*******************************************************/
 
extern TABLE tagtable;
extern TYP *head;
extern TYP stdconst;
extern int bit_next;
extern int bit_offset;
extern int bit_width;
 
__int16 typeno = bt_last;
 
void ParseStructMembers(TYP *tp, int ztype);
 
void ParseStructDeclaration(int ztype)
{
SYM *sp;
TYP *tp;
bit_offset = 0;
bit_next = 0;
bit_width = -1;
if(lastst == id) {
if((sp = search(lastid,&tagtable)) == NULL) {
sp = allocSYM();
sp->name = litlate(lastid);
sp->tp = allocTYP();
sp->tp->type = ztype;
sp->tp->typeno = typeno++;
sp->tp->lst.head = 0;
sp->storage_class = sc_type;
sp->tp->sname = sp->name;
NextToken();
if(lastst != begin)
error(ERR_INCOMPLETE);
else {
insert(sp,&tagtable);
NextToken();
ParseStructMembers(sp->tp,ztype);
}
}
else
NextToken();
head = sp->tp;
}
else {
tp = allocTYP();
tp->type = ztype;
tp->sname = 0;
tp->lst.head = 0;
if( lastst != begin)
error(ERR_INCOMPLETE);
else {
NextToken();
ParseStructMembers(tp,ztype);
}
head = tp;
}
}
 
void ParseStructMembers(TYP *tp, int ztype)
{
int slc;
slc = 0;
tp->val_flag = 1;
while( lastst != end) {
if(ztype == bt_struct)
slc += declare(&(tp->lst),sc_member,slc,ztype);
else
slc = imax(slc,declare(&tp->lst,sc_member,0,ztype));
}
bit_offset = 0;
bit_next = 0;
bit_width = -1;
tp->size = slc;
NextToken();
}
 
/Cglbdef.c
0,0 → 1,65
#include <stdio.h>
#include "c.h"
#include "expr.h"
#include "Statement.h"
#include "gen.h"
/*
* 68000 C compiler
*
* Copyright 1984, 1985, 1986 Matthew Brandt.
* all commercial rights reserved.
*
* This compiler is intended as an instructive tool for personal use. Any
* use for profit without the written consent of the author is prohibited.
*
* This compiler may be distributed freely for non-commercial use as long
* as this notice stays intact. Please forward any enhancements or questions
* to:
*
* Matthew Brandt
* Box 920337
* Norcross, Ga 30092
*/
 
/*******************************************************
Modified to support Raptor64 'C64' language
by Robert Finch
robfinch@opencores.org
*******************************************************/
 
/* global definitions */
 
FILE *input = 0,
*list = 0,
*output = 0;
 
int lineno = 0;
int nextlabel = 0;
int lastch = 0;
int lastst = 0;
char lastid[33] = "";
char laststr[MAX_STRLEN + 1] = "";
__int64 ival = 0;
double rval = 0.0;
 
TABLE gsyms[257],// = {0,0},
lsyms = {0,0};
SYM *lasthead = NULL;
struct slit *strtab = 0;
int lc_static = 0;
int lc_auto = 0;
struct snode *bodyptr = 0;
int global_flag = 1;
TABLE defsyms = {0,0};
int save_mask = 0; /* register save mask */
TYP tp_int, tp_econst;
 
int isPascal = FALSE;
int isOscall = FALSE;
int isInterrupt = FALSE;
int isNocall = FALSE;
int optimize = TRUE;
int exceptions = FALSE;
SYM *currentFn = NULL;
int callsFn = FALSE;
 
/Cmain.c
0,0 → 1,130
#include <stdio.h>
#include <string.h>
#include "c.h"
#include "expr.h"
#include "gen.h"
#include "cglbdec.h"
 
/*
* 68000 C compiler
*
* Copyright 1984, 1985, 1986 Matthew Brandt.
* all commercial rights reserved.
*
* This compiler is intended as an instructive tool for personal use. Any
* use for profit without the written consent of the author is prohibited.
*
* This compiler may be distributed freely for non-commercial use as long
* as this notice stays intact. Please forward any enhancements or questions
* to:
*
* Matthew Brandt
* Box 920337
* Norcross, Ga 30092
*/
/*******************************************************
Modified to support Raptor64 'C64' language
by Robert Finch
robfinch@opencores.org
*******************************************************/
 
void makename(char *s, char *e);
void summary();
int options(char *);
int openfiles(char *);
void closefiles();
 
char infile[20],
listfile[20],
outfile[20];
extern TABLE tagtable;
int mainflag;
extern int total_errors;
int uctran_off;
 
int main(int argc, char **argv)
{
uctran_off = 0;
while(--argc) {
if( **++argv == '-')
options(*argv);
else if( openfiles(*argv)) {
lineno = 0;
initsym();
memset(gsyms,0,sizeof(gsyms));
getch();
NextToken();
compile();
summary();
ReleaseGlobalMemory();
closefiles();
}
}
getchar();
return 0;
}
 
int options(char *s)
{
optimize =1;
exceptions=1;
if (s[1]=='o')
optimize = 0;
return 0;
}
 
int openfiles(char *s)
{
int ofl;
strcpy(infile,s);
strcpy(listfile,s);
strcpy(outfile,s);
makename(listfile,".lis");
makename(outfile,".s");
if( (input = fopen(infile,"r")) == 0) {
printf(" cant open %s\n",infile);
return 0;
}
ofl = _creat(outfile,-1);
if( ofl < 0 )
{
printf(" cant create %s\n",outfile);
fclose(input);
return 0;
}
if( (output = _fdopen(ofl,"w")) == 0) {
printf(" cant open %s\n",outfile);
fclose(input);
return 0;
}
if( (list = fopen(listfile,"w")) == 0) {
printf(" cant open %s\n",listfile);
fclose(input);
fclose(output);
return 0;
}
return 1;
}
 
void makename(char *s, char *e)
{
while(*s != 0 && *s != '.')
++s;
while(*s++ = *e++);
}
 
void summary()
{
printf("\n -- %d errors found.",total_errors);
fprintf(list,"\f\n *** global scope typedef symbol table ***\n\n");
ListTable(&gsyms,0);
fprintf(list,"\n *** structures and unions ***\n\n");
ListTable(&tagtable,0);
}
 
void closefiles()
{
fclose(input);
fclose(output);
fclose(list);
}
/GenerateShift.c
0,0 → 1,117
// ============================================================================
// (C) 2012 Robert Finch
// All Rights Reserved.
// robfinch<remove>@opencores.org
//
// C64 - Raptor64 'C' derived language compiler
// - 64 bit CPU
//
// This source file is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file 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 this program. If not, see <http://www.gnu.org/licenses/>.
//
// ============================================================================
//
#include <stdio.h>
#include "c.h"
#include "expr.h"
#include "Statement.h"
#include "gen.h"
#include "cglbdec.h"
 
 
AMODE *GenerateShift(ENODE *node,int flags, int size, int op)
{
AMODE *ap1, *ap2;
 
ap1 = GenerateExpression(node->p[0],F_REG,size);
ap2 = GenerateExpression(node->p[1],F_REG | F_IMMED,8);
switch(op) {
case op_shru:
switch (size) {
case 8: GenerateTriadic(op_andi,0,ap1,ap1,make_immed(0xff)); break;
case 16: GenerateTriadic(op_andi,0,ap1,ap1,make_immed(0xffff)); break;
case 32: GenerateTriadic(op_andi,0,ap1,ap1,make_immed(0xffffffff)); break;
default: ;
}
break;
case op_shr:
switch (size) {
case 8: GenerateTriadic(op_sext8,0,ap1,ap1,NULL); break;
case 16: GenerateTriadic(op_sext16,0,ap1,ap1,NULL); break;
case 32: GenerateTriadic(op_sext32,0,ap1,ap1,NULL); break;
default: ;
}
break;
}
if (ap2->mode==am_immed) {
switch(op)
{
case op_shl: op = op_shli; break;
case op_shr: op = op_shri; break;
case op_shru: op = op_shrui; break;
}
GenerateTriadic(op,0,ap1,ap1,make_immed(ap2->offset->i));
}
else
GenerateTriadic(op,0,ap1,ap1,ap2);
ReleaseTempRegister(ap2);
MakeLegalAmode(ap1,flags,size);
return ap1;
}
 
 
/*
* generate shift equals operators.
*/
struct amode *GenerateAssignShift(ENODE *node,int flags,int size,int op)
{
struct amode *ap1, *ap2, *ap3;
 
ap3 = GenerateExpression(node->p[0],F_ALL,size);
ap2 = GenerateExpression(node->p[1],F_REG | F_IMMED,size);
if (ap3->mode != am_reg) {
ap1 = GetTempRegister();
GenerateDiadic(op_lw,0,ap1,ap3);
}
else
ap1 = ap3;
switch(op) {
case op_shru:
switch (size) {
case 8: GenerateTriadic(op_andi,0,ap1,ap1,make_immed(0xff)); break;
case 16: GenerateTriadic(op_andi,0,ap1,ap1,make_immed(0xffff)); break;
case 32: GenerateTriadic(op_andi,0,ap1,ap1,make_immed(0xffffffff)); break;
default: ;
}
break;
case op_shr:
switch (size) {
case 8: GenerateTriadic(op_sext8,0,ap1,ap1,NULL); break;
case 16: GenerateTriadic(op_sext16,0,ap1,ap1,NULL); break;
case 32: GenerateTriadic(op_sext32,0,ap1,ap1,NULL); break;
default: ;
}
break;
}
if (ap2->mode==am_immed)
GenerateTriadic(op,0,ap1,ap1,make_immed(ap2->offset->i));
else
GenerateTriadic(op,0,ap1,ap1,ap2);
if (ap3->mode != am_reg) {
GenerateDiadic(op_sw,0,ap1,ap3);
}
ReleaseTempRegister(ap2);
MakeLegalAmode(ap1,flags,size);
return ap1;
}
 
/Cglbdec.h
0,0 → 1,151
/*
* 68000 C compiler
*
* Copyright 1984, 1985, 1986 Matthew Brandt.
* all commercial rights reserved.
*
* This compiler is intended as an instructive tool for personal use. Any
* use for profit without the written consent of the author is prohibited.
*
* This compiler may be distributed freely for non-commercial use as long
* as this notice stays intact. Please forward any enhancements or questions
* to:
*
* Matthew Brandt
* Box 920337
* Norcross, Ga 30092
*/
 
/* global ParseSpecifierarations */
 
extern FILE *input,
*list,
*output;
 
extern int lineno;
extern int nextlabel;
extern int lastch;
extern int lastst;
extern char lastid[33];
extern char laststr[MAX_STLP1];
extern __int64 ival;
extern double rval;
 
extern TABLE gsyms[257],
lsyms;
extern SYM *lasthead;
extern struct slit *strtab;
extern int lc_static;
extern int lc_auto;
extern struct snode *bodyptr; /* parse tree for function */
extern int global_flag;
extern TABLE defsyms;
extern int save_mask; /* register save mask */
extern int uctran_off;
extern int isPascal;
extern int isOscall;
extern int isInterrupt;
extern int isNocall;
extern int asmblock;
extern int optimize;
extern int exceptions;
extern SYM *currentFn;
 
extern void error(int n);
extern void needpunc(enum e_sym p);
// Memmgt.c
extern char *xalloc(int);
extern SYM *allocSYM();
extern TYP *allocTYP();
extern AMODE *allocAmode();
 
// NextToken.c
extern void initsym();
extern void NextToken();
extern int getch();
extern int isspace(char c);
extern void getbase(b);
extern void SkipSpaces();
 
// Stmt.c
extern struct snode *ParseCompoundStatement();
 
extern void GenerateDiadic(int op, int len, struct amode *ap1,struct amode *ap2);
// Symbol.c
extern SYM *gsearch(char *na);
extern SYM *search(char *na,SYM *thead);
extern void insert(SYM* sp, TABLE *table);
 
extern char *litlate(char *);
// Decl.c
extern void dodecl(int defclass);
extern void ParseParameterDeclarations(int);
extern void ParseAutoDeclarations();
extern void ParseSpecifier(TABLE *table);
extern void ParseDeclarationPrefix();
extern void ParseStructDeclaration(int);
extern void ParseEnumerationList(TABLE *table);
 
extern void initstack();
extern int getline(int listflag);
 
// Init.c
extern void doinit(SYM *sp);
// Func.c
extern void funcbody(SYM *sp);
// Intexpr.c
extern int GetIntegerExpression();
// Expr.c
extern ENODE *makenode(int nt, ENODE *v1, ENODE *v2);
extern ENODE *makeinode(int nt, __int64 v1);
extern TYP *expression(struct enode **node);
extern int IsLValue(struct enode *node);
// Optimize.c
extern void opt4(struct enode **node);
// GenerateStatement.c
extern void GenerateStatement(struct snode *stmt);
extern void GenerateFunction(struct snode *stmt);
extern void GenerateIntoff(struct snode *stmt);
extern void GenerateInton(struct snode *stmt);
extern void GenerateStop(struct snode *stmt);
extern void GenerateAsm(struct snode *stmt);
extern void GenerateFirstcall(struct snode *stmt);
extern void gen_regrestore();
extern AMODE *make_direct(__int64 i);
// Outcode.c
extern void GenerateByte(int val);
extern void GenerateChar(int val);
extern void genhalf(int val);
extern void GenerateWord(__int64 val);
extern void GenerateLong(int val);
extern void genstorage(int nbytes);
extern void GenerateReference(SYM *sp,int offset);
extern void GenerateLabelReference(int n);
extern void gen_strlab(char *s);
extern void dumplits();
extern int stringlit(char *s);
extern void nl();
extern void cseg();
extern void dseg();
extern void put_code(int op, int len,AMODE *aps, AMODE *apd, AMODE *);
extern void put_label(int lab);
// Peepgen.c
extern void flush_peep();
extern void GenerateLabel(int labno);
// Gencode.c
extern AMODE *make_label(__int64 lab);
extern AMODE *make_immed(__int64);
extern AMODE *make_indirect(int i);
extern AMODE *make_offset(struct enode *node);
extern void swap_nodes(struct enode *node);
extern int isshort(struct enode *node);
// IdentifyKeyword.c
extern int IdentifyKeyword();
// Preproc.c
extern int preprocess();
// CodeGenerator.c
extern AMODE *make_indirect(int i);
extern AMODE *make_indexed(__int64 o, int i);
extern void GenerateFalseJump(struct enode *node,int label);
 


powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.