📄 codeavr.c
字号:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "defs.h"
#include "data.h"
#include "headers.h"
// Some predefinitions:
//
// INTSIZE is the size of an integer in the target machine
// BYTEOFF is the offset of an byte within an integer on the
// target machine. (ie: 8080,pdp11 = 0, 6809 = 1,
// 360 = 3)
// This compiler assumes that an integer is the SAME length as
// a pointer - in fact, the compiler uses INTSIZE for both.
#define INTSIZE 2 // can't really be changed for AVR
#define BYTEOFF 1
#define LABEL_PREFIX "_"
#define GLOBAL_PREFIX "_"
#define CHECKBYTE 0x55
static GetMemChar(int ptr, int offset);
static GetMemInt(int ptr, int offset);
static GetMemLong(int ptr, int offset);
static int CheckExtFun(char *p);
static struct t_fn
{
char name[20];
int flag;
} extfunlist[] = {"structoffset",0,
"sextx",0,
"sextz",0,
"div",0,
"mul",0,
"neg",0,
"putstk_l",0,
"putstk_i_x", 0,
"putstk_i_z", 0,
"glpp",0,
"push_l",0,
"pop_l",0,
"sub_l",0,
"div_l",0,
"le",0,
"_case",0,
"",0 };
static int CheckExtFun(char *p) {
int i;
i = 0;
while (strlen(extfunlist[i].name) > 0) {
if (strcmp(extfunlist[i].name, p) == 0) {
if (extfunlist[i].flag == 0) {
extfunlist[i].flag = 1;
return FALSE;
}
else
return TRUE;
}
else
i++;
}
return FALSE;
}
// print all assembler info before any code is generated
void header(void) {
char ttt[100];
outstr(";**********************************************************\n");
outstr("; Small C for AVR\n;");
FEvers();
outstr("; Modifications and AVR code Copyright (C) by Ron Kreymborg\n");
outstr(";**********************************************************\n");
outstr("#include\t<avr.inc>\n");
if (incname[0]) {
strcpy(ttt, "#include\t<");
strcat(ttt, incname);
strcat(ttt, ">\n");
outstr(ttt);
}
outstr("\tcol\t132\n");
outstr("\tlstexp-\n");
ot("module\t");
outstr(module);
nl();
gtext();
}
void jmptable(void) {
}
void nl(void) {
outbyte(EOL);
}
void initmac(void) {
defmac("smallc\t1");
}
int galign(int t) {
return(t);
}
// return size of an integer
int intsize(void) {
return(INTSIZE);
}
// return offset of ls byte within word
// (ie: 8080 & pdp11 is 0, 6809 is 1, 360 is 3)
int byteoff(void) {
return(BYTEOFF);
}
// Emit user label prefix
void LabPrefix(void) {
outstr(LABEL_PREFIX);
}
void NamePrefix(void) {
outstr(GLOBAL_PREFIX);
}
void InsertPrefix(char *t) {
strcpy(t, GLOBAL_PREFIX);
}
// Emit internal label prefix
void internal_prefix(void) {
outstr(GLOBAL_PREFIX);
}
// Save C machine state
void PushState(void) {
ol("push\tr16");
ol("in\tr16,0x3f");
ol("push\tr16");
ol("push\tr0");
ol("push\tr1");
ol("push\tr2");
ol("push\tr3");
ol("push\tr4");
ol("push\tr5");
ol("push\tr6");
ol("push\tr7");
ol("push\tr8");
ol("push\tr9");
ol("push\tr10");
ol("push\tr11");
ol("push\tr12");
ol("push\tr13");
ol("push\tr14");
ol("push\tr15");
ol("push\tr17");
ol("push\tr18");
ol("push\tr19");
ol("push\tr20");
ol("push\tr21");
ol("push\tr22");
ol("push\tr23");
ol("push\tr24");
ol("push\tr25");
ol("push\tr26");
ol("push\tr27");
ol("push\tr28");
ol("push\tr29");
ol("push\tr30");
ol("push\tr31");
}
// Restore C machine state
void PopState(void) {
ol("pop\tr31");
ol("pop\tr30");
ol("pop\tr29");
ol("pop\tr28");
ol("pop\tr27");
ol("pop\tr26");
ol("pop\tr25");
ol("pop\tr24");
ol("pop\tr23");
ol("pop\tr22");
ol("pop\tr21");
ol("pop\tr20");
ol("pop\tr19");
ol("pop\tr18");
ol("pop\tr17");
ol("pop\tr15");
ol("pop\tr14");
ol("pop\tr13");
ol("pop\tr12");
ol("pop\tr11");
ol("pop\tr10");
ol("pop\tr9");
ol("pop\tr8");
ol("pop\tr7");
ol("pop\tr6");
ol("pop\tr5");
ol("pop\tr4");
ol("pop\tr3");
ol("pop\tr2");
ol("pop\tr1");
ol("pop\tr0");
ol("pop\tr16");
ol("out\t0x3f,r16");
ol("pop\tr16");
ol("reti");
}
// Output internal generated label prefix
void olprfix(void) {
outbyte('L');
}
// Output a label definition terminator
void col(void) {
outbyte(':');
}
// begin a comment line for the assembler
void comment(void) {
outbyte(';');
}
// print any assembler stuff needed after all code
void trailer(void) {
ol("end");
}
// function prologue
void prologue(void) {
ot("ldiz\t");
onum(softstklimit);
outstr("\t\t; initialise for stack monitoring");
nl();
ot("ldi\tr20,");
onum(CHECKBYTE);
nl();
ol("st\tz+,r20");
ol("st\tz+,r20");
if (hardstklimit != 0xffff) {
ot("ldiz\t");
onum(hardstklimit);
nl();
ol("st\tz+,r20");
ol("st\tz+,r20");
}
}
void CheckCode(void) {
outstr("_ChkSoftStk");
nl();
ot("ldix\t");
onum(softstklimit);
outstr("\t\t; Stack monitoring code");
nl();
ol("ld\tr20,x+");
ot("cpi\tr20,");
onum(CHECKBYTE);
nl();
ol("brne\t_SoftErr");
ol("ld\tr20,x+");
ot("cpi\tr20,");
onum(CHECKBYTE);
nl();
ol("brne\t_SoftErr");
ol("ret");
outstr("_SoftErr");
nl();
ot("in\tr20,");
onum(StkErrPort);
nl();
ot("cbr\tr20,");
onum(StkErrBit[1]);
nl();
ot("out\t");
onum(StkErrPort);
outstr(",r20\n");
ol("rjmp\t$");
if (hardstklimit != 0xffff) {
outstr("_ChkHardStk");
nl();
ot("ldix\t");
onum(hardstklimit);
nl();
ol("ld\tr20,x+");
ot("cpi\tr20,");
onum(CHECKBYTE);
nl();
ol("brne\t_HardErr");
ol("ld\tr20,x+");
ot("cpi\tr20,");
onum(CHECKBYTE);
nl();
ol("brne\t_HardErr");
ol("ret");
outstr("_HardErr");
nl();
ot("in\tr20,");
onum(StkErrPort);
nl();
ot("cbr\tr20,");
onum(StkErrBit[0]);
nl();
ot("out\t");
onum(StkErrPort);
outstr(",r20\n");
ol("rjmp\t$");
}
}
// text (code) segment
void gtext(void) {
ol("rseg\tscode");
}
// data segment
void gdata(void) {
ol("rseg\tsdata");
}
// provide the next available register(s)
int getregister(int type, int ident, int value) {
int retval, bytes;
bytes = 1; // assume char
if (type == CLONG)
bytes = 4;
else
if (type == CINT || type == UCINT || ident == POINTER)
bytes = intsize();
if (NextReg + bytes > REGS)
return -1;
retval = REGBASE - NextReg;
NextReg += bytes;
return (retval);
}
// Restore the register boundary
void ResetRegBoundary(void) {
NextReg = 0;
}
// Indicate register usage
void regsummary(void)
{
outstr(";\tNext register free: r");
onum(REGBASE-NextReg);
nl();
}
// Output the variable symbol at scptr as an extern or a public
void ppubext(int scptr) {
char text[50];
if (symtab[scptr].storage == STATIC)
return;
ot(symtab[scptr].storage == EXTERN ? "extern\t" : "public\t");
InsertPrefix(text);
strcat(text, symtab[scptr].name);
outstr(text);
nl();
}
// Output the function symbol at scptr as an extern or a public
void fpubext(int scptr) {
char text[50];
if (symtab[scptr].storage == STATIC || symtab[scptr].type == STRUCTDEF)
return;
ot(symtab[scptr].offset == FUNCTION ? "public\t" : "extern\t");
InsertPrefix(text);
strcat(text, symtab[scptr].name);
outstr(text);
nl();
}
// Output a number
void onum(int num) {
outdec(num);
}
// print partial instruction to get an immediate value into
// the primary register
void immed(STATE *stpt) {
if (!(stpt->ident == FUNCTION || stpt->ident == FUNCDEF) && (stpt->storage == PUBLIC || stpt->storage == STATIC || stpt->storage == EXTERN)) {
stkptr++;
stack[stkptr].type = stpt->type;
stack[stkptr].storage = stpt->storage;
}
else {
ot("ldiz\t");
InX = 0;
}
}
void outname (char *p) {
if (stkptr)
strcpy(stack[stkptr].name, p);
else
outstr(p);
}
void doimmed(STATE *stpt, char *sname, int offset) {
if (stpt->storage == AUTO) {
if (offset) {
if (InX)
ot("adiw\tr26,");
else
ot("adiw\tr30,");
onum(offset);
nl();
}
}
else {
if (InX) {
ot("ldi\tr31,high(");
outstr(stack[stkptr].name);
if (offset) {
outstr("+");
onum(offset);
}
outstr(")\n");
ot("ldi\tr30,low(");
outstr(stack[stkptr].name);
if (offset) {
outstr("+");
onum(offset);
}
outstr(")\n");
InX = 0;
}
else {
ot("ldi\tr27,high(");
outstr(stack[stkptr].name);
if (offset) {
outstr("+");
onum(offset);
}
outstr(")\n");
ot("ldi\tr26,low(");
outstr(stack[stkptr].name);
if (offset) {
outstr("+");
onum(offset);
}
outstr(")\n");
InX = 1;
}
}
}
void long_immed(void) {
ot("ldil\t");
}
void doStructOff(int offset) {
ot("ldi\tr25,");
onum(offset>>8);
ot("; ");
onum(offset);
nl();
ot("ldi\tr24,");
onum(offset & 0xff);
nl();
gcall("structoffset", CINT);
}
void gintoff(void) {
ol("cli\t; interrupts off");
}
void ginton(void) {
ol("sei\t; interrupts on");
}
// Fetch a static memory cell into the primary register.
// Do a cast if required.
void getmem(STATE *stpt) {
int ptr;
ptr = stpt->ptr;
if (stkptr && (stpt->type == VOID || stpt->type == UCINT || stpt->type == CINT || (stpt->ident == POINTER && !stpt->pointing))) {
// ol("ldd\tr0,z+1");
// ol("ld\tr31,z");
// ol("mov\tr30,r0");
if (stpt->ident == FUNCTION || stpt->ident == ARRAY) {
ot("ldi\tr31,high(");
outstr(stack[stkptr].name);
outstr(")\n");
ot("ldi\tr30,low(");
outstr(stack[stkptr].name);
outstr(")\n");
stkptr--;
return;
}
if (InX || (stpt->ident == FUNCPTR || (Indexing && stpt->ident != POINTER)))
ot("lds\tr31,");
else
ot("lds\tr27,");
outstr(stack[stkptr].name);
nl();
if (InX || stpt->ident == FUNCPTR || (Indexing && stpt->ident != POINTER)) {
ot("lds\tr30,");
InX = 0;
}
else {
ot("lds\tr26,");
InX = 1;
}
outstr(stack[stkptr].name);
outstr("+1\n");
stkptr--;
}
else
if (stkptr && (stpt->type == CCHAR || stpt->type == UCCHAR)) {
if ((CallFunction || stkptr) && stpt->ident == ARRAY) {
ot("ldi\tr31,high(");
outstr(stack[stkptr].name);
outstr(")\n");
ot("ldi\tr30,low(");
outstr(stack[stkptr].name);
outstr(")\n");
stkptr--;
InX = 0;
return;
}
if (InX || stpt->ident == FUNCPTR || stpt->ident != POINTER) {
ot("lds\tr30,");
InX = 0;
}
else {
ot("lds\tr26,");
InX = 1;
}
outstr(stack[stkptr].name);
nl();
if (IfFlag || Indexing)
sign_extend_int(stpt);
stkptr--;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -