215 lines
5.4 KiB
C
215 lines
5.4 KiB
C
|
/* ===========================================================================
|
||
|
* uz80as, an assembler for the Zilog Z80 and several other microprocessors.
|
||
|
*
|
||
|
* Intel 8080.
|
||
|
* ===========================================================================
|
||
|
*/
|
||
|
|
||
|
#include "pp.h"
|
||
|
#include "err.h"
|
||
|
#include "options.h"
|
||
|
#include "uz80as.h"
|
||
|
#include <stddef.h>
|
||
|
|
||
|
/* pat:
|
||
|
* a: expr
|
||
|
* b: B,C,D,E,H,L,M,A
|
||
|
* c: B,D,H,SP
|
||
|
* d: B,D
|
||
|
* e: B,D,H,PSW
|
||
|
* f: JNZ,JZ,JNC,JC,JPO,JPE,JP,JM
|
||
|
* g: CNZ,CZ,CNC,CC,CPO,CPE,CP,CM
|
||
|
* h: RNZ,RZ,RNC,RC,RPO,RPE,RP,RM
|
||
|
* i: B,C,D,E,H,L,A
|
||
|
* j: ADD,ADC,SUB,SBB,ANA,XRA,ORA,CMP
|
||
|
* k: RLC,RRC,RAL,RAR
|
||
|
* l: ADI,ACI,SUI,SBI,ANI,XRI,ORI,CPI
|
||
|
* m: SHLD,LHLD,STA,LDA
|
||
|
* n: DI,EI
|
||
|
* o: OUT,IN
|
||
|
* p: STC,CMC
|
||
|
* q: POP,PUSH
|
||
|
* r: STAX,LDAX
|
||
|
*
|
||
|
* gen:
|
||
|
* .: output lastbyte
|
||
|
* b: (op << 3) | lastbyte
|
||
|
* c: op | lastbyte
|
||
|
* d: lastbyte = op as 8 bit value
|
||
|
* e: output op as word (no '.' should follow)
|
||
|
* f: (op << 4) | lastbyte
|
||
|
* g: possible value to RST
|
||
|
* h: (op << 2) | lastbyte
|
||
|
*/
|
||
|
|
||
|
static const struct matchtab s_matchtab_i8080[] = {
|
||
|
{ "MOV M,i", "70c0.", 3, 0 },
|
||
|
{ "MOV i,M", "46b0.", 3, 0 },
|
||
|
{ "MOV i,i", "40b0c1.", 3, 0 },
|
||
|
{ "MVI b,a", "06b0.d1.", 3, 0, "e8" },
|
||
|
{ "LXI c,a", "01f0.e1", 3, 0 },
|
||
|
{ "m a", "22b0.e1", 3, 0 },
|
||
|
{ "r d", "02b0f1.", 3, 0 },
|
||
|
{ "XCHG", "EB.", 3, 0 },
|
||
|
{ "j b", "80b0c1.", 3, 0 },
|
||
|
{ "l a", "C6b0.d1.", 3, 0, "e8" },
|
||
|
{ "INR b", "04b0.", 3, 0 },
|
||
|
{ "DCR b", "05b0.", 3, 0 },
|
||
|
{ "INX c", "03f0.", 3, 0 },
|
||
|
{ "DCX c", "0Bf0.", 3, 0 },
|
||
|
{ "DAD c", "09f0.", 3, 0 },
|
||
|
{ "DAA", "27.", 3, 0 },
|
||
|
{ "k", "07b0.", 3, 0 },
|
||
|
{ "CMA", "2F.", 3, 0 },
|
||
|
{ "p", "37b0.", 3, 0 },
|
||
|
{ "JMP a", "C3.e0", 3, 0 },
|
||
|
{ "f a", "C2b0.e1", 3, 0 },
|
||
|
{ "CALL a", "CD.e0", 3, 0 },
|
||
|
{ "g a", "C4b0.e1", 3, 0 },
|
||
|
{ "RET", "C9.", 3, 0 },
|
||
|
{ "h", "C0b0.", 3, 0 },
|
||
|
{ "RST a", "C7g0.", 3, 0, "b3" },
|
||
|
{ "PCHL", "E9.", 3, 0 },
|
||
|
{ "q e", "C1h0f1.", 3, 0 },
|
||
|
{ "XTHL", "E3.", 3, 0 },
|
||
|
{ "SPHL", "F9.", 3, 0 },
|
||
|
{ "o a", "D3b0.d1.", 3, 0, "e8" },
|
||
|
{ "n", "F3b0.", 3, 0 },
|
||
|
{ "HLT", "76.", 3, 0 },
|
||
|
{ "NOP", "00.", 3, 0 },
|
||
|
/* 8085 added instructions */
|
||
|
{ "RIM", "20.", 2, 0 },
|
||
|
{ "SIM", "30.", 2, 0 },
|
||
|
{ "ARHL", "10.", 2, 2 },
|
||
|
{ "DSUB", "08.", 2, 2 },
|
||
|
{ "RDEL", "18.", 2, 2 },
|
||
|
{ "LDHI a", "28.d0.", 2, 2, "e8" },
|
||
|
{ "LDSI a", "38.d0.", 2, 2, "e8" },
|
||
|
{ "RSTV", "CB.", 2, 2 },
|
||
|
{ "SHLX", "D9.", 2, 2 },
|
||
|
{ "LHLX", "ED.", 2, 2 },
|
||
|
{ "JNK a", "DD.e0", 2, 2 },
|
||
|
{ "JNX5 a", "DD.e0", 2, 2 },
|
||
|
{ "JNUI a", "DD.e0", 2, 2 },
|
||
|
{ "JK a", "FD.e0", 2, 2 },
|
||
|
{ "JX5 a", "FD.e0", 2, 2 },
|
||
|
{ "JUI a", "FD.e0", 2, 2 },
|
||
|
{ NULL, NULL },
|
||
|
};
|
||
|
|
||
|
static const char *const bval[] = { "B", "C", "D", "E",
|
||
|
"H", "L", "M", "A", NULL };
|
||
|
static const char *const cval[] = { "B", "D", "H", "SP", NULL };
|
||
|
static const char *const dval[] = { "B", "D", NULL };
|
||
|
static const char *const eval[] = { "B", "D", "H", "PSW", NULL };
|
||
|
static const char *const fval[] = { "JNZ", "JZ", "JNC", "JC",
|
||
|
"JPO", "JPE", "JP", "JM", NULL };
|
||
|
static const char *const gval[] = { "CNZ", "CZ", "CNC", "CC",
|
||
|
"CPO", "CPE", "CP", "CM", NULL };
|
||
|
static const char *const hval[] = { "RNZ", "RZ", "RNC", "RC",
|
||
|
"RPO", "RPE", "RP", "RM", NULL };
|
||
|
static const char *const ival[] = { "B", "C", "D", "E",
|
||
|
"H", "L", "", "A", NULL };
|
||
|
static const char *const jval[] = { "ADD", "ADC", "SUB", "SBB",
|
||
|
"ANA", "XRA", "ORA", "CMP", NULL };
|
||
|
static const char *const kval[] = { "RLC", "RRC", "RAL", "RAR", NULL };
|
||
|
static const char *const lval[] = { "ADI", "ACI", "SUI", "SBI",
|
||
|
"ANI", "XRI", "ORI", "CPI", NULL };
|
||
|
static const char *const mval[] = { "SHLD", "LHLD", "STA", "LDA", NULL };
|
||
|
static const char *const nval[] = { "DI", "EI", NULL };
|
||
|
static const char *const oval[] = { "OUT", "IN", NULL };
|
||
|
static const char *const pval[] = { "STC", "CMC", NULL };
|
||
|
static const char *const qval[] = { "POP", "PUSH", NULL };
|
||
|
static const char *const rval[] = { "STAX", "LDAX", NULL };
|
||
|
|
||
|
static const char *const *const valtab[] = {
|
||
|
bval, cval, dval, eval, fval,
|
||
|
gval, hval, ival, jval, kval,
|
||
|
lval, mval, nval, oval, pval,
|
||
|
qval, rval
|
||
|
};
|
||
|
|
||
|
static int match_i8080(char c, const char *p, const char **q)
|
||
|
{
|
||
|
int v;
|
||
|
|
||
|
if (c <= 'r') {
|
||
|
v = mreg(p, valtab[(int) (c - 'b')], q);
|
||
|
} else {
|
||
|
v = -1;
|
||
|
}
|
||
|
|
||
|
return v;
|
||
|
}
|
||
|
|
||
|
static int gen_i8080(int *eb, char p, const int *vs, int i, int savepc)
|
||
|
{
|
||
|
int b;
|
||
|
|
||
|
b = *eb;
|
||
|
switch (p) {
|
||
|
case 'f': b |= (vs[i] << 4); break;
|
||
|
case 'g': if (s_pass > 0 && (vs[i] & ~7) != 0) {
|
||
|
eprint(_("invalid RST argument (%d)\n"),
|
||
|
vs[i]);
|
||
|
eprcol(s_pline, s_pline_ep);
|
||
|
newerr();
|
||
|
}
|
||
|
b |= (vs[i] << 3);
|
||
|
break;
|
||
|
case 'h': b |= (vs[i] << 2); break;
|
||
|
default:
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
*eb = b;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int s_pat_char = 'b';
|
||
|
static int s_pat_index;
|
||
|
|
||
|
static void pat_char_rewind_i8080(int c)
|
||
|
{
|
||
|
s_pat_char = c;
|
||
|
s_pat_index = 0;
|
||
|
};
|
||
|
|
||
|
static const char *pat_next_str_i8080(void)
|
||
|
{
|
||
|
const char *s;
|
||
|
|
||
|
if (s_pat_char >= 'b' && s_pat_char <= 'r') {
|
||
|
s = valtab[(int) (s_pat_char - 'b')][s_pat_index];
|
||
|
if (s != NULL) {
|
||
|
s_pat_index++;
|
||
|
}
|
||
|
} else {
|
||
|
s = NULL;
|
||
|
}
|
||
|
|
||
|
return s;
|
||
|
};
|
||
|
|
||
|
const struct target s_target_i8080 = {
|
||
|
.id = "i8080",
|
||
|
.descr = "Intel 8080",
|
||
|
.matcht = s_matchtab_i8080,
|
||
|
.matchf = match_i8080,
|
||
|
.genf = gen_i8080,
|
||
|
.pat_char_rewind = pat_char_rewind_i8080,
|
||
|
.pat_next_str = pat_next_str_i8080,
|
||
|
.mask = 1
|
||
|
};
|
||
|
|
||
|
const struct target s_target_i8085 = {
|
||
|
.id = "i8085",
|
||
|
.descr = "Intel 8085",
|
||
|
.matcht = s_matchtab_i8080,
|
||
|
.matchf = match_i8080,
|
||
|
.genf = gen_i8080,
|
||
|
.pat_char_rewind = pat_char_rewind_i8080,
|
||
|
.pat_next_str = pat_next_str_i8080,
|
||
|
.mask = 2
|
||
|
};
|