Line 7... |
Line 7... |
// Purpose: Like asmdata.h, this contains necessary data structures for the
|
// Purpose: Like asmdata.h, this contains necessary data structures for the
|
// assembler. Specifically, in C/C++ fashion, this contains most
|
// assembler. Specifically, in C/C++ fashion, this contains most
|
// of the code for actually building such structures.
|
// of the code for actually building such structures.
|
//
|
//
|
// Creator: Dan Gisselquist, Ph.D.
|
// Creator: Dan Gisselquist, Ph.D.
|
// Gisselquist Tecnology, LLC
|
// Gisselquist Technology, LLC
|
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// Copyright (C) 2015, Gisselquist Technology, LLC
|
// Copyright (C) 2015, Gisselquist Technology, LLC
|
//
|
//
|
Line 222... |
Line 222... |
|
|
#define BLD_DUALOP(OP) \
|
#define BLD_DUALOP(OP) \
|
if (m_opa == zp.ZIP_Rnone) \
|
if (m_opa == zp.ZIP_Rnone) \
|
yyerror("Err: Dual Ops need a result register"); \
|
yyerror("Err: Dual Ops need a result register"); \
|
if (m_opb != zp.ZIP_Rnone) { \
|
if (m_opb != zp.ZIP_Rnone) { \
|
if(!fitsin(imm, 16)) \
|
if(!fitsin(imm, 14)) \
|
yyerror("16-bit: Immediate out of range"); \
|
yyerror("14-bit: Immediate out of range"); \
|
in = zp.OP(m_cond,imm,m_opb,m_opa); \
|
in = zp.OP(m_cond,imm,m_opb,m_opa); \
|
} else { \
|
} else { \
|
if(!fitsin(imm, 20)) \
|
if(!fitsin(imm, 18)) \
|
yyerror("20-bit: Immediate out of range"); \
|
yyerror("18-bit: Immediate out of range"); \
|
in = zp.OP(m_cond,imm,m_opa); \
|
in = zp.OP(m_cond,imm,m_opa); \
|
}
|
}
|
|
|
#define BLD_BRANCH(OP,CND) \
|
#define BLD_BRANCH(OP,CND) \
|
if (fitsin(offset, 16)) \
|
if (fitsin(offset, 13)) \
|
in = zp.OP(offset); \
|
in = zp.OP(offset); \
|
else if (fitsin(offset, 20)) \
|
else if (fitsin(offset, 18)) \
|
in = zp.op_add(zp.CND, offset, zp.ZIP_PC); \
|
in = zp.op_add(zp.CND, offset, zp.ZIP_PC); \
|
else { in = zp.OP(offset); yyerror("LONG JUMP NOT SUPPORTED"); }
|
else { in = zp.OP(offset); yyerror("LONG JUMP NOT SUPPORTED"); }
|
|
|
ASMLINE *TLINE::eval(void) {
|
ASMLINE *TLINE::eval(void) {
|
ZIPI in;
|
ZIPI in;
|
Line 270... |
Line 270... |
case OP_MOV:
|
case OP_MOV:
|
if ((m_opa == zp.ZIP_Rnone)||(m_opb == zp.ZIP_Rnone)) {
|
if ((m_opa == zp.ZIP_Rnone)||(m_opb == zp.ZIP_Rnone)) {
|
yyerror("Moves can only occurr between registers");
|
yyerror("Moves can only occurr between registers");
|
fprintf(stderr, "m_opa = %d, m_opb = %d\n", m_opa, m_opb);
|
fprintf(stderr, "m_opa = %d, m_opb = %d\n", m_opa, m_opb);
|
fprintf(stderr, "m_imm = %d\n", imm);
|
fprintf(stderr, "m_imm = %d\n", imm);
|
} else if (!fitsin(imm, 16))
|
} else if (!fitsin(imm, 13))
|
yyerror("Immediate overflow on move");
|
yyerror("Immediate overflow on move");
|
in = zp.op_mov(m_cond, imm, m_opb, m_opa);
|
in = zp.op_mov(m_cond, imm, m_opb, m_opa);
|
break;
|
break;
|
case OP_LDIHI:
|
case OP_LDIHI:
|
if ((imm & (-1<<16))!=0)
|
if ((imm & (-1<<16))!=0)
|
Line 356... |
Line 356... |
if (m_opb != zp.ZIP_Rnone)
|
if (m_opb != zp.ZIP_Rnone)
|
in = zp.op_sto(m_cond, m_opa, imm, m_opb);
|
in = zp.op_sto(m_cond, m_opa, imm, m_opb);
|
else
|
else
|
in = zp.op_sto(m_cond, m_opa, imm);
|
in = zp.op_sto(m_cond, m_opa, imm);
|
break;
|
break;
|
|
case OP_BREV:
|
|
BLD_DUALOP(op_brev);
|
|
break;
|
|
case OP_POPC:
|
|
BLD_DUALOP(op_popc);
|
|
break;
|
case OP_LDI:
|
case OP_LDI:
|
if ((!fitsin(imm, 24))||(m_cond != zp.ZIPC_ALWAYS)) {
|
if ((!fitsin(imm, 23))||(m_cond != zp.ZIPC_ALWAYS)) {
|
if (m_opa == zp.ZIP_PC)
|
if (m_opa == zp.ZIP_PC)
|
yyerror("Cannot LDI 32-bit addresses into PC register!");
|
yyerror("Cannot LDI 32-bit addresses into PC register!");
|
LLINE *lln = new LLINE;
|
LLINE *lln = new LLINE;
|
lln->addline(new ILINE(zp.op_ldihi(m_cond, (imm>>16)&0x0ffff, m_opa)));
|
lln->addline(new ILINE(zp.op_ldihi(m_cond, (imm>>16)&0x0ffff, m_opa)));
|
lln->addline(new ILINE(zp.op_ldilo(m_cond, imm&0x0ffff, m_opa)));
|
lln->addline(new ILINE(zp.op_ldilo(m_cond, imm&0x0ffff, m_opa)));
|
lln->m_lineno = m_lineno;
|
lln->m_lineno = m_lineno;
|
return lln;
|
return lln;
|
} else
|
} else
|
in = zp.op_ldi(imm, m_opa);
|
in = zp.op_ldi(imm, m_opa);
|
break;
|
break;
|
|
case OP_DIVU:
|
|
BLD_DUALOP(op_divu);
|
|
break;
|
|
case OP_DIVS:
|
|
BLD_DUALOP(op_divs);
|
|
break;
|
case OP_CLRF:
|
case OP_CLRF:
|
in = zp.op_clrf(m_cond, m_opb);
|
in = zp.op_clrf(m_cond, m_opb);
|
break;
|
break;
|
case OP_NOT:
|
case OP_NOT:
|
in = zp.op_not(m_cond, m_opb);
|
in = zp.op_not(m_cond, m_opb);
|
Line 390... |
Line 402... |
}break;
|
}break;
|
case OP_JMP:
|
case OP_JMP:
|
if (m_opb == zp.ZIP_Rnone) {
|
if (m_opb == zp.ZIP_Rnone) {
|
if (m_cond != zp.ZIPC_ALWAYS)
|
if (m_cond != zp.ZIPC_ALWAYS)
|
yyerror("JMP: Conditions are not allowed for absolute jumps.");
|
yyerror("JMP: Conditions are not allowed for absolute jumps.");
|
imm &= (1<<24)-1;
|
imm &= (1<<23)-1;
|
if (!fitsin(imm, 24))
|
if (!fitsin(imm, 23))
|
yyerror("JMP: Absolute jump address out of range");
|
yyerror("JMP: Absolute jump address out of range");
|
in = zp.op_ldi(imm, zp.ZIP_PC);
|
in = zp.op_ldi(imm, zp.ZIP_PC);
|
} else if (fitsin(imm,16)) {
|
} else if (fitsin(imm,13)) {
|
in = zp.op_mov(m_cond, imm, m_opb, zp.ZIP_PC);
|
in = zp.op_mov(m_cond, imm, m_opb, zp.ZIP_PC);
|
} else if (fitsin(imm,20))
|
} else if (fitsin(imm,18))
|
in = zp.op_add(m_cond, imm, m_opb, zp.ZIP_PC);
|
in = zp.op_add(m_cond, imm, m_opb, zp.ZIP_PC);
|
else
|
else
|
yyerror("JMP: Immediate out of range");
|
yyerror("JMP: Immediate out of range");
|
break;
|
break;
|
case OP_BRA:
|
case OP_BRA:
|
Line 436... |
Line 448... |
case OP_TRAP:
|
case OP_TRAP:
|
if((m_opb == zp.ZIP_Rnone)&&(m_cond == zp.ZIPC_ALWAYS))
|
if((m_opb == zp.ZIP_Rnone)&&(m_cond == zp.ZIPC_ALWAYS))
|
in = zp.op_ldi(imm, zp.ZIP_CC);
|
in = zp.op_ldi(imm, zp.ZIP_CC);
|
else if((m_opb == zp.ZIP_Rnone)&&((imm&0x0ffdf)==imm))
|
else if((m_opb == zp.ZIP_Rnone)&&((imm&0x0ffdf)==imm))
|
in = zp.op_ldilo(m_cond, imm & 0x0ffdf, zp.ZIP_CC);
|
in = zp.op_ldilo(m_cond, imm & 0x0ffdf, zp.ZIP_CC);
|
else if((m_opb != zp.ZIP_Rnone)&&(fitsin(imm, 16)))
|
else if((m_opb != zp.ZIP_Rnone)&&(fitsin(imm, 13)))
|
in = zp.op_mov(m_cond, imm, m_opb, zp.ZIP_CC);
|
in = zp.op_mov(m_cond, imm, m_opb, zp.ZIP_CC);
|
else {
|
else {
|
yyerror("Illegal trap!");
|
yyerror("Illegal trap!");
|
in = zp.op_trap(m_cond, 0);
|
in = zp.op_trap(m_cond, 0);
|
}
|
}
|
break;
|
break;
|
case OP_RETN: in = zp.op_retn(m_cond); break;
|
case OP_RETN: // yywarn("RETN opcode is deprecated");
|
|
in = zp.op_lod(m_cond, imm, m_opb, m_opa);
|
|
in = zp.op_lod(m_cond, -1, zp.ZIP_SP, zp.ZIP_PC);
|
|
break;
|
case OP_HALT: in = zp.op_halt(m_cond); break;
|
case OP_HALT: in = zp.op_halt(m_cond); break;
|
case OP_RTU: in = zp.op_rtu(m_cond); break;
|
case OP_RTU: in = zp.op_rtu(m_cond); break;
|
case OP_BUSY: in = zp.op_busy(m_cond); break;
|
case OP_BUSY: in = zp.op_busy(m_cond); break;
|
case OP_BREAK: in = zp.op_break(); break;
|
|
case OP_NOOP: in = zp.op_noop(); break;
|
case OP_NOOP: in = zp.op_noop(); break;
|
|
case OP_BREAK: in = zp.op_break(); break;
|
|
case OP_LOCK: in = zp.op_lock(); break;
|
// OP_LJMP:
|
// OP_LJMP:
|
case OP_NONE:
|
case OP_NONE:
|
default: { char ebuf[256]; sprintf(ebuf, "Unrecognized OP-Code, %d, NONE = %d, CLR=%d", m_opcode, OP_NONE, OP_CLR);
|
default: { char ebuf[256]; sprintf(ebuf, "Unrecognized OP-Code, %d, NONE = %d, CLR=%d", m_opcode, OP_NONE, OP_CLR);
|
yyerror(ebuf);
|
yyerror(ebuf);
|
in = zp.op_noop(); break;
|
in = zp.op_noop(); break;
|
Line 463... |
Line 479... |
}
|
}
|
|
|
int TLINE::nlines(void) {
|
int TLINE::nlines(void) {
|
if ((m_opcode == OP_LDI)&&( (!(m_imm->isdefined()))
|
if ((m_opcode == OP_LDI)&&( (!(m_imm->isdefined()))
|
|| (m_cond != ZPARSER::ZIPC_ALWAYS)
|
|| (m_cond != ZPARSER::ZIPC_ALWAYS)
|
|| (!fitsin(m_imm->eval(), 24)) )) {
|
|| (!fitsin(m_imm->eval(), 23)) )) {
|
return 2;
|
return 2;
|
}
|
}
|
return 1;
|
return 1;
|
}
|
}
|
|
|
Line 558... |
Line 574... |
case OP_BUSY: fprintf(fp, "\tTLINE OP = BUSY\n");
|
case OP_BUSY: fprintf(fp, "\tTLINE OP = BUSY\n");
|
break;
|
break;
|
case OP_BREAK: fprintf(fp, "\tTLINE OP = BREAK\n");
|
case OP_BREAK: fprintf(fp, "\tTLINE OP = BREAK\n");
|
break;
|
break;
|
case OP_NOOP: fprintf(fp, "\tTLINE OP = NOOP\n");
|
case OP_NOOP: fprintf(fp, "\tTLINE OP = NOOP\n");
|
|
case OP_LOCK: fprintf(fp, "\tTLINE OP = LOCK\n");
|
break;
|
break;
|
// OP_LJMP:
|
// OP_LJMP:
|
case OP_NONE:
|
case OP_NONE:
|
default:
|
default:
|
fprintf(fp, "\tTLINE OP = (Unrecognized, %d)\n", m_opcode);
|
fprintf(fp, "\tTLINE OP = (Unrecognized, %d)\n", m_opcode);
|