?? asm.c
字號:
}
else if (isdigit(**pp)) {
if (**pp == '0') {
++*pp;
if (**pp == 'x' || **pp == 'X') {
while (isxdigit(*++*pp))
;
c = **pp;
**pp = 0;
t.type = CON;
sscanf(p1, "%x", &t.u.con);
**pp = c;
return t;
}
--*pp;
}
while (isdigit(*++*pp))
;
c = **pp;
**pp = 0;
t.type = CON;
t.u.con = atoi(p1);
**pp = c;
}
else {
t.type = **pp;
++*pp;
}
return t;
}
Bool parse(char**p, ...)
{
va_list va;
Token t;
Type expected;
Bool ret = TRUE;
va_start(va, p);
while ((expected = va_arg(va, Type)) != 0) {
t = lex(p);
if (t.type != expected) {
error("syntax error");
ret = FALSE;
break;
}
if (t.type == SYM || t.type == REG || t.type == CON) {
Token* pt = va_arg(va, Token*);
*pt = t;
}
}
va_end(va);
return ret;
}
enum { NSYMS = 10000 };
static int nsyms = 0;
static Symbol symtab[NSYMS];
/* Look-up symbol for string in current file's symbol table.
* If found, return symbol.
* If not, create new symbol and return that.
*
* Each source file has its own logical name space.
* Global names (sym.file == 0) are visible across all files.
*/
Sym lookup(SZ sz)
{
int i;
for (i = 0; i < nsyms; i++)
if ((symtab[i].file == 0 || symtab[i].file == file) &&
strncmp(symtab[i].id, sz, sizeof(symtab[i].id)-1) == 0)
return &symtab[i];
/* not found, add it */
if (nsyms < NSYMS) {
strncpy(symtab[i].id, sz, sizeof(symtab[i].id)-1);
symtab[nsyms].addr = 0;
symtab[nsyms].defined = FALSE;
symtab[nsyms].file = file;
return &symtab[nsyms++];
}
else
return 0;
}
int cmpAddr(const void* pv1, const void* pv2)
{
const Symbol* ps1 = pv1;
const Symbol* ps2 = pv2;
return ps1->addr - ps2->addr;
}
SZ szForAddr(char buf[], size_t cbbuf, Addr addr)
{
static Bool sorted = FALSE;
Symbol *p, *base = 0;
if (!sorted) {
qsort(symtab, nsyms, sizeof(symtab[0]), cmpAddr);
sorted = TRUE;
}
/* find last symbol address <= addr
*
* Takes advantage of the invariant that symbols are in order
* of increasing address.
*/
for (p = symtab; p < &symtab[nsyms] && p->addr <= addr; p++)
if (p->id[0] != 'L') /* skip labels */
base = p;
if (base && !(strcmp(base->id, "end")==0 || strcmp(base->id, "__end")==0)) {
if (addr == base->addr)
_snprintf(buf, cbbuf, "%s", base->id);
else
_snprintf(buf, cbbuf, "%s+%d", base->id, addr - base->addr);
} else
_snprintf(buf, cbbuf, "%04X", addr);
buf[cbbuf-1] = 0;
return buf;
}
enum { cbMax = 65536 };
Byte rgb[cbMax];
unsigned cb = 0;
Addr here()
{
return cb;
}
void label(Sym sym)
{
sym->addr = cb;
sym->defined = TRUE;
}
void global(Sym sym)
{
sym->file = 0;
}
int lastDestReg()
{
Insn insn = (rgb[cb-2] << 8) | rgb[cb-1];
if (OP_ADD <= OP(insn) && OP(insn) < OP_SW)
return RD(insn);
else
return 0;
}
void insn(unsigned in, unsigned w) {
word(mpininsn[in] | w);
}
void align(unsigned alignment) {
while (cb % alignment != 0)
byte(0);
}
void bss(unsigned c) {
while (c--)
byte(0);
}
void word(unsigned w) {
align(2);
byte(w >> 8);
byte(w);
}
unsigned wordAt(Addr addr) {
return (rgb[addr] << 8) | rgb[addr+1];
}
void byte(unsigned b) {
if (cb < sizeof(rgb))
rgb[cb++] = (Byte)b;
}
enum { NFIXUPS = 10000 };
Fixup fixups[NFIXUPS];
int cfixup = 0;
void fixup(FixupType type, Sym target, int disp)
{
if (cfixup < NFIXUPS) {
fixups[cfixup].type = type;
fixups[cfixup].target = target;
fixups[cfixup].addr = cb;
fixups[cfixup].disp = disp;
++cfixup;
}
}
void applyFixups() {
Fixup* pfix;
for (pfix = fixups; pfix < &fixups[cfixup]; pfix++) {
int disp;
unsigned abs;
if (!pfix->target->defined && !pfix->target->error) {
error("undefined symbol '%s'", pfix->target->id);
pfix->target->error = TRUE;
continue;
}
switch (pfix->type) {
case FIX_ADDR:
abs = pfix->target->addr + pfix->disp;
rgb[pfix->addr ] = abs >> 8;
rgb[pfix->addr+1] = abs;
break;
case FIX_LDST: {
Insn imm = (rgb[pfix->addr] << 8) | rgb[pfix->addr+1];
Insn insn = (rgb[pfix->addr+2] << 8) | rgb[pfix->addr+3];
Bool byte = (OP(insn) == OP_LB || OP(insn) == OP_SB || OP(insn) == OP_ADDI);
Bool word = (OP(insn) == OP_LW || OP(insn) == OP_SW || OP(insn) == OP_JAL);
abs = pfix->target->addr + pfix->disp;
if (OP(imm) != OP_IMM || !(byte || word)) {
error("ldst fixup error");
break;
}
else if ((abs&1) && word) {
error("ldst word fixup error target '%s' odd address %04X + %d", pfix->target->id, pfix->target->addr, pfix->disp);
break;
}
imm = mpininsn[IMM] | IMM12(abs >> 4);
insn = (insn & ~0xF) | INSN_I4(abs);
rgb[pfix->addr ] = imm >> 8;
rgb[pfix->addr+1] = (Byte)imm;
rgb[pfix->addr+2] = insn >> 8;
rgb[pfix->addr+3] = (Byte)insn;
break;
}
case FIX_BR:
disp = ((int)pfix->target->addr - (int)pfix->addr)/2 - 2;
if (-128 <= disp && disp < 128)
rgb[pfix->addr+1] = (Byte)disp;
else
error("branch displacement overflow at %04X target '%s'", pfix->addr, pfix->target->id);
break;
case FIX_CALL:
if ((pfix->target->addr & 0xF) == 0) {
rgb[pfix->addr] |= (pfix->target->addr >> 12) & 0x0F;
rgb[pfix->addr+1] |= (pfix->target->addr >> 4) & 0xFF;
}
else
error("call at %04X target '%s' is not 16-byte aligned", pfix->addr, pfix->target->id);
break;
default:
error("unexpected fixup type");
break;
}
}
}
void addListingLine(SZ line) {
if (nlines < NLINES) {
lines[nlines].addr = here();
lines[nlines].szLine = _strdup(line);
++nlines;
}
}
void listing(SZ lstfile) {
FILE* lst;
Addr addr;
Insn insn;
time_t now;
struct tm* ptmNow;
char szInsn[20];
static char rev[] = "$Revision: 3 $";
if ((lst = fopen(lstfile, "w")) == 0) {
error("cannot open '%s' (%s)", lstfile, strerror(errno));
return;
}
time(&now);
ptmNow = localtime(&now);
rev[strlen(rev)-2] = 0;
fprintf(lst, "# generated by xr16 rev.%s on %s\n", rev+11, asctime(ptmNow));
fprintf(lst, "addr code disassembly source\n");
fprintf(lst, "---- ---- ----------- ------\n");
line = 0;
for (addr = 0; addr < cb; addr += sizeof(Insn)) {
while (line+1 < nlines && lines[line].addr <= addr && lines[line+1].addr <= addr)
fprintf(lst, "%-28s %s\n", "", lines[line++].szLine);
insn = wordAt(addr);
szForInsn(szInsn, sizeof szInsn, addr, insn);
fprintf(lst, "%04X %04X %-18s", addr, insn, szInsn);
if (line < nlines && lines[line].addr <= addr)
fprintf(lst, "%s\n", lines[line++].szLine);
else
fprintf(lst, "\n");
}
for ( ; line < nlines; ++line)
fprintf(lst, "%-28s %s\n", "", lines[line].szLine);
if (ferror(lst) || fclose(lst))
error("error writing '%s' (%s)", lstfile, strerror(errno));
}
void emit(SZ hexfile) {
FILE* hex;
Addr addr;
if ((hex = fopen(hexfile, "w")) == 0) {
error("cannot open '%s' (%s)", hexfile, strerror(errno));
return;
}
for (addr = 0; addr < cb; addr++) {
if (addr % 16 == 0)
fprintf(hex, "- %02X %04X", __min(0x10, cb - addr), addr);
fprintf(hex, " %02X", rgb[addr]);
if (addr % 16 == 15 || addr == cb-1)
fprintf(hex, "\n");
}
if (ferror(hex) || fclose(hex))
error("error writing '%s' (%s)", hexfile, strerror(errno));
}
static SZ mprnsz[16] = {
"r0", "r1", "r2", "r3",
"r4", "r5", "r6", "r7",
"r8", "r9", "r10", "r11",
"r12", "r13", "sp", "r15"
};
static SZ mpopsz[16] = {
"add %s,%s,%s",
"sub %s,%s,%s",
"addi %s,%s,%d",
0,
0,
"lw %s,%d(%s)",
"lb %s,%d(%s)",
0,
"sw %s,%d(%s)",
"sb %s,%d(%s)",
"jal %s,%d(%s)",
0,
"call %04X",
"imm %04X",
0,
"trap %d"
};
static SZ mpfnszRR[16] = {
"and %s,%s",
"or %s,%s",
"xor %s,%s",
"andn %s,%s",
"adc %s,%s",
"sbc %s,%s"
};
static SZ mpfnszRI[16] = {
"andi %s,%d",
"ori %s,%d",
"xori %s,%d",
"andni %s,%d",
"adci %s,%d",
"sbci %s,%d",
"srli %s,%d",
"srai %s,%d",
"slli %s,%d",
"srxi %s,%d",
"slxi %s,%d",
};
SZ mpcondszBR[16] = {
"br %04X",
"brn",
"beq %04X",
"bne %04X",
"bc %04X",
"bnc %04X",
"bv %04X",
"bnv %04X",
"blt %04X",
"bge %04X",
"ble %04X",
"bgt %04X",
"bltu %04X",
"bgeu %04X",
"bleu %04X",
"bgtu %04X"
};
SZ szForInsn(char buf[], size_t cbbuf, Addr addr, Insn insn) {
strcpy(buf, "<reserved>");
buf[--cbbuf] = 0;
switch (OP(insn)) {
case OP_ADD:
case OP_SUB:
_snprintf(buf, cbbuf, mpopsz[OP(insn)], mprnsz[RD(insn)], mprnsz[RA(insn)], mprnsz[RB(insn)]);
break;
case OP_ADDI:
_snprintf(buf, cbbuf, mpopsz[OP(insn)], mprnsz[RD(insn)], mprnsz[RA(insn)], IMM_SEXT(insn));
break;
case OP_RR:
if (mpfnszRR[FN(insn)])
_snprintf(buf, cbbuf, mpfnszRR[FN(insn)], mprnsz[RD(insn)], mprnsz[RB(insn)]);
break;
case OP_RI:
if (mpfnszRI[FN(insn)])
_snprintf(buf, cbbuf, mpfnszRI[FN(insn)], mprnsz[RD(insn)], IMM_SEXT(insn));
break;
case OP_LW:
case OP_SW:
case OP_JAL:
_snprintf(buf, cbbuf, mpopsz[OP(insn)], mprnsz[RD(insn)], (((IMM(insn)>>1)<<1)|((IMM(insn)&1)<<4)), mprnsz[RA(insn)]);
break;
case OP_LB:
case OP_SB:
_snprintf(buf, cbbuf, mpopsz[OP(insn)], mprnsz[RD(insn)], IMM(insn), mprnsz[RA(insn)]);
break;
case OP_BR:
if (mpcondszBR[COND(insn)])
_snprintf(buf, cbbuf, mpcondszBR[COND(insn)], addr + (DISP(insn) + 2)*sizeof(Insn));
break;
case OP_CALL:
case OP_IMM:
_snprintf(buf, cbbuf, mpopsz[OP(insn)], IMM12(insn) << 4);
break;
case OP_TRAP:
_snprintf(buf, cbbuf, mpopsz[OP(insn)], IMM12(insn));
break;
}
buf[cbbuf] = 0;
return buf;
}
SZ mpinsz[] = {
"and", "sub", "addi",
"and", "or", "xor", "andn", "adc", "sbc",
"andi", "ori", "xori", "andni", "adci", "sbci", "srli", "srai", "slli", "srxi", "slxi",
"lw", "lb", 0, "sw", "sb", "jal",
"br", "brn", "beq", "bne", "bc", "bnc", "bv", "bnv",
"blt", "bge", "ble", "bgt", "bltu", "bgeu", "bleu", "bgtu",
"call", "imm", 0
};
Insn mpininsn[] = {
INSN_OP(OP_ADD),
INSN_OP(OP_SUB),
INSN_OP(OP_ADDI),
INSN_OPFN(OP_RR, FN_AND),
INSN_OPFN(OP_RR, FN_OR),
INSN_OPFN(OP_RR, FN_XOR),
INSN_OPFN(OP_RR, FN_ANDN),
INSN_OPFN(OP_RR, FN_ADC),
INSN_OPFN(OP_RR, FN_SBC),
INSN_OPFN(OP_RI, FN_AND),
INSN_OPFN(OP_RI, FN_OR),
INSN_OPFN(OP_RI, FN_XOR),
INSN_OPFN(OP_RI, FN_ANDN),
INSN_OPFN(OP_RI, FN_ADC),
INSN_OPFN(OP_RI, FN_SBC),
INSN_OPFN(OP_RI, FN_SRL),
INSN_OPFN(OP_RI, FN_SRA),
INSN_OPFN(OP_RI, FN_SLL),
INSN_OPFN(OP_RI, FN_SRX),
INSN_OPFN(OP_RI, FN_SLX),
INSN_OP(OP_LW),
INSN_OP(OP_LB),
INSN_OP(OP_SW),
INSN_OP(OP_SB),
INSN_OP(OP_JAL),
INSN_BR(BR_BR),
INSN_BR(BR_BRN),
INSN_BR(BR_BEQ),
INSN_BR(BR_BNE),
INSN_BR(BR_BC),
INSN_BR(BR_BNC),
INSN_BR(BR_BV),
INSN_BR(BR_BNV),
INSN_BR(BR_BLT),
INSN_BR(BR_BGE),
INSN_BR(BR_BLE),
INSN_BR(BR_BGT),
INSN_BR(BR_BLTU),
INSN_BR(BR_BGEU),
INSN_BR(BR_BLEU),
INSN_BR(BR_BGTU),
INSN_OP(OP_CALL),
INSN_OP(OP_IMM),
INSN_OP(OP_TRAP),
};
SzToken tokens[] = {
{ "add", { IN, ADD } },
{ "sub", { IN, SUB } },
{ "addi", { IN, ADDI } },
{ "and", { IN, AND } },
{ "or", { IN, OR } },
{ "xor", { IN, XOR } },
{ "andn", { IN, ANDN } },
{ "adc", { IN, ADC } },
{ "sbc", { IN, SBC } },
{ "andi", { IN, ANDI } },
{ "ori", { IN, ORI } },
{ "xori", { IN, XORI } },
{ "andni", { IN, ANDNI } },
{ "adci", { IN, ADCI } },
{ "sbci", { IN, SBCI } },
{ "srli", { IN, SRLI } },
{ "srai", { IN, SRAI } },
{ "slli", { IN, SLLI } },
{ "srxi", { IN, SRXI } },
{ "slxi", { IN, SLXI } },
{ "lw", { IN, LW } },
{ "lb", { IN, LB } },
{ "sw", { IN, SW } },
{ "sb", { IN, SB } },
{ "jal", { IN, JAL } },
{ "br", { IN, BR } },
{ "brn", { IN, BRN } },
{ "beq", { IN, BEQ } },
{ "bne", { IN, BNE } },
{ "bc", { IN, BC } },
{ "bnc", { IN, BNC } },
{ "bv", { IN, BV } },
{ "bnv", { IN, BNV } },
{ "blt", { IN, BLT } },
{ "bge", { IN, BGE } },
{ "ble", { IN, BLE } },
{ "bgt", { IN, BGT } },
{ "bltu", { IN, BLTU } },
{ "bgeu", { IN, BGEU } },
{ "bleu", { IN, BLEU } },
{ "bgtu", { IN, BGTU, } },
{ "call", { IN, CALL } },
{ "imm", { IN, IMM } },
{ "trap", { IN, TRAP } },
{ "nop", { IN, NOP } },
{ "mov", { IN, MOV } },
{ "subi", { IN, SUBI } },
{ "cmp", { IN, CMP } },
{ "cmpi", { IN, CMPI } },
{ "lea", { IN, LEA } },
{ "j", { IN, J } },
{ "ret", { IN, RET } },
{ "reti", { IN, RETI } },
{ "sext", { IN, SEXT } },
{ "zext", { IN, ZEXT } },
{ "lbs", { IN, LBS } },
{ "addl", { IN, ADDL } },
{ "subl", { IN, SUBL } },
{ "andl", { IN, ANDL } },
{ "orl", { IN, ORL } },
{ "xorl", { IN, XORL } },
{ "andnl", { IN, ANDNL } },
{ "movl", { IN, MOVL } },
{ "cmpl", { IN, CMPL } },
{ "ll", { IN, LL } },
{ "sl", { IN, SL } },
{ "global", { IN, GLOBAL } },
{ "align", { IN, ALIGN } },
{ "byte", { IN, BYTE_ } },
{ "word", { IN, WORD_ } },
{ "bss", { IN, BSS } },
{ "r0", { REG, 0 } },
{ "r1", { REG, 1 } },
{ "r2", { REG, 2 } },
{ "r3", { REG, 3 } },
{ "r4", { REG, 4 } },
{ "r5", { REG, 5 } },
{ "r6", { REG, 6 } },
{ "r7", { REG, 7 } },
{ "r8", { REG, 8 } },
{ "r9", { REG, 9 } },
{ "r10", { REG, 10 } },
{ "r11", { REG, 11 } },
{ "r12", { REG, 12 } },
{ "r13", { REG, 13 } },
{ "r14", { REG, 14 } },
{ "r15", { REG, 15 } },
{ "sp", { REG, 13 } },
{ 0 }
};
extern SZ szProgram;
extern int errors;
int error(SZ szError, ...) {
va_list va;
char error[BUFSIZ], prefix[BUFSIZ], listing[BUFSIZ];
++errors;
va_start(va, szError);
_vsnprintf(error, sizeof error, szError, va);
va_end(va);
error[sizeof(error)-1] = 0;
if (szCurrentFile) {
if (line)
_snprintf(prefix, sizeof prefix, "%s(%d): %s", szCurrentFile, line, error);
else
_snprintf(prefix, sizeof prefix, "%s: %s", szCurrentFile, error);
}
else
_snprintf(prefix, sizeof prefix, "%s", error);
prefix[sizeof(prefix)-1] = 0;
if (szProgram)
fprintf(stderr, "%s: ", szProgram);
fprintf(stderr, "%s\n", prefix);
fflush(stderr);
_snprintf(listing, sizeof listing, "# error %s", prefix);
listing[sizeof(listing)-1] = 0;
addListingLine(listing);
return 1;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -