diff options
Diffstat (limited to 'igen/sux-igen')
| -rw-r--r-- | igen/sux-igen/addr-modes.igen | 91 | ||||
| -rw-r--r-- | igen/sux-igen/inst.igen | 245 | ||||
| -rw-r--r-- | igen/sux-igen/utils.igen | 50 | 
3 files changed, 386 insertions, 0 deletions
| diff --git a/igen/sux-igen/addr-modes.igen b/igen/sux-igen/addr-modes.igen new file mode 100644 index 0000000..3780ed2 --- /dev/null +++ b/igen/sux-igen/addr-modes.igen @@ -0,0 +1,91 @@ +#include "utils.igen" + +%% + +/* +am((abs|zm)[xy]?) { +	if (am == zmx || am == absx) { +		idx = cpu->x; +	} else if (am == zmy || am == absy) { +		idx = cpu->y; +	} + +	if (am == abs || am == absx || am == absy) { +		is_abs = 1; +	} + +	size = ((prefix & 0xC) >> 1) | is_abs; +	addr = read(cpu->pc, size) + idx; +	value = read(addr, rs); +} + +am((a)?ind([xy])?) { +	if (am == indx || am == aindx) { +		idx = cpu->x; +		pre_idx = 1; +	} else if (am == indy || am == aindy) { +		idx = cpu->y; +	} + +	if (am == aind || am == aindx || am == aindy) { +		is_abs = 1; +	} + +	size = ((prefix & 0xC) >> 1) | is_abs; + +	if (pre_idx) { +		addr = read(read(cpu->pc + idx, size), 7); +	} else { +		addr = read(read(cpu->pc, size), 7) + idx; +	} + +	value = read(addr, rs); +} + +am(eind) { +	addr = cpu->e; +	value = read(addr, rs); +} +*/ + +am(abs|zm([xy])?) { +	if (am == abs) { +		mem_type = ABS; +	} else { +		if (am == zmx) { +			idx = cpu->x; +		} else if (am == zmy) { +			idx = cpu->y; +		} +		mem_type = ZM; +	} +	addr = read_addr(prefix, mem_type) + idx; +	value = read(addr, rs); +} + +am(ind([xy])?) { +	if (am == indx) { +		idx = cpu->x; +		pre_idx = 1; +	} else if (am == indy) { +		idx = cpu->y; +	} +	mem_type = ZM; +	addr = ind_idx_addr(prefix, mem_type, idx, pre_idx); +	value = read(addr, rs); +} + +am(rel) { +	addr = rel_addr(prefix); +} + +am(imm) { +	value = read(cpu->pc, rs); +	cpu->pc += rs+1; +} + +am(breg) { +	value = cpu->b; +} + +%% diff --git a/igen/sux-igen/inst.igen b/igen/sux-igen/inst.igen new file mode 100644 index 0000000..791ad2c --- /dev/null +++ b/igen/sux-igen/inst.igen @@ -0,0 +1,245 @@ +#include "utils.igen" +#include "addr-modes.igen" + +%% + +(ad|sb|breg(in|de))c, and, (or|st|ld|t[bxy]|p[hl])a, xor, (ls|ro)[lr], mul, div, asr, cmp { +	reg = &cpu->a; +} + +(ld|st|cp|in|de|ta|p[hl])b { +	reg = &cpu->b; +} + +(ld|st|cp|in|de|t[ays]|p[hl])x { +	reg = &cpu->x; +} + +(ld|st|cp|in|de|t[ax]|p[hl])y { +	reg = &cpu->y; +} + +txs { +	reg = &cpu->sp; +} + +cps, (cl|se)[cio], clv, b(po|n[ge]|[cv][sc]|eq|r[ak]), p[hl]p { +	reg = &cpu->ps; +} + +ta[bxy] { +	reg2 = &cpu->a; +} + +tba, ~breg(div) { +	reg2 = &cpu->b; +} + +tx[ay], breg(div) { +	reg2 = &cpu->x; +} + +ty[ax] { +	reg2 = &cpu->y; +} + +tsx { +	reg2 = &cpu->sp; +} + +ld[abxy] { +	*reg = value; +	update_flags_nz(value); +} + +st[abxy] { +	value = *reg; +	write(value, addr, rs); +} + +(in|de)[cbxy] { +	if (addr_mode == impl) { +		value = *reg; +	} +	if (inst.match[0] == in) { +		++value; +	} else if (inst.match[0] == de) { +		--value; +	} +	if (addr_mode != impl) { +		msb = rs*8; +		write(value, addr, rs); +	} else { +		*reg = value; +	} +	update_flags_nz(value); +} + +ph[abxyp] { +	if (inst == php) { +		rs = 0; +	} +	push(*reg, rs); +} + +pl[abxyp] { +	if (inst == plp) { +		rs = 0; +	} +	*reg = pull(rs); +} + +/* +ora, and, xor { +	switch (inst) { +		case and: sum = *reg & value; break; +		case ora: sum = *reg | value; break; +		case xor: sum = *reg ^ value; break; +	} +	*reg = sum; +	update_flags_nz(sum); +} +*/ + +ora { +	sum = *reg | value; +	*reg = sum; +	update_flags_nz(sum); +} + +and { +	sum = *reg & value; +	*reg = sum; +	update_flags_nz(sum); +} + +xor { +	sum = *reg ^ value; +	*reg = sum; +	update_flags_nz(sum); +} + +(se|cl)c { +	cpu->ps.C = (inst == sec); +} + +(se|cl)i { +	cpu->ps.I = (inst == sei); +} + +(se|cl)o { +	if (ext == base && mode == base) { +		cpu->ps.O = (inst == seo); +	} +} + +clv { +	cpu->ps.V = 0; +} + +cps { +	cpu->ps = 0; +} + +b(po|ng) { +	cpu->pc = jump(addr, cpu->pc, get_flag(inst, bpo, cpu->ps.N)); +} + +bc[sc] { +	cpu->pc = jump(addr, cpu->pc, get_flag(inst, bcs, cpu->ps.C)); +} + +b(ne|eq) { +	cpu->pc = jump(addr, cpu->pc, get_flag(inst, beq, cpu->ps.Z)); +} + +bv[sc] { +	cpu->pc = jump(addr, cpu->pc, get_flag(inst, bvs, cpu->ps.V)); +} + +bra, j(mp|sr) { +	if (inst == jsr) { +		push(cpu->pc, (rs) ? rs : 7); +	} +	cpu->pc = jump(addr, cpu->pc, 1); +} + +intr(irq|nmi|reset), brk, wai { +	if (inst == nmi) { +		addr = 0xFFA0; +	} else if (inst == reset) { +		addr = 0xFFC0; +	} else if (inst == irq) { +		addr = 0xFFE0; +	} else { +		addr = 0xFFF0; +	} + +	if (inst != reset) { +		if (!cpu->is_wait) { +			push(cpu->pc, 7); +			push(cpu->ps, 0); +			cpu->ps.I = 1; +		} +		cpu->is_wait = (inst == wai); +	} +	if (inst != wai) { +		addr = read(addr, 7); +		cpu->pc = jump(addr, cpu->pc, 1); +	} +} + +rt[si] { +	if (inst == rti) { +		cpu->ps = pull(0); +	} +	cpu->pc = pull(7); +} + +(ad|sb)c { +	if (inst == sbc) { +		value = ~value; +	} +	*reg = adc(*reg, value, cpu->ps.C); +} + +c(mp|p[bxy]) { +	adc(*reg, ~value, 1); +} + +(asr|ls[lr]) { +	if (inst == lsl) { +		sum = (value < msb) ? shift(*reg, value, 0, <<) : 0; +		cpu->ps.C = (*reg >> (msb-(value+!value))) & 1; +	} else { +		if (inst == asr) { +			sign = -(uint64_t)(*reg >> (msb-1)) << (msb-1)-value; +		} +		sum = (value < msb) ? shift(*reg, value, sign, >>) : 0; +		cpu->ps.C = (*reg >> (value-(value != 0))) & 1; +	} +} + +ro[lr] { +	if (inst == rol) { +		rotate(sum, *reg, value, <<, >>, cpu->ps.C, cpu->ps.C << (value-1)); +		cpu->ps.C = (*reg >> (msb-(value+!value))) & 1; +	} else { +		rotate(sum, *reg, value, >>, <<, cpu->ps.C << (msb-1), cpu->ps.C << (msb-value)); +		cpu->ps.C = (*reg >> (value-(value != 0))) & 1; +	} +} + +mul { +	*reg = mul(*reg, value); +} + +div { +	*reg = div(*reg, value, reg2); +} + +t(a[bxy]|ba|x[ays]|y[ax]|sx) { +	*reg = *reg2; +	update_flags_nz(*reg); +} +%% diff --git a/igen/sux-igen/utils.igen b/igen/sux-igen/utils.igen new file mode 100644 index 0000000..7385117 --- /dev/null +++ b/igen/sux-igen/utils.igen @@ -0,0 +1,50 @@ +update_flags_nz(value) { +	cpu->ps.N = bit(value, msb-1); +	cpu->ps.Z = value == 0; +} + +get_flag(name, match, flag) { +	if (name == match) { +		return flag; +	} else { +		return !flag; +	} +} + +jump(addr, fallback, flag) { +	if (flag) { +		return addr; +	} else { +		return fallback; +	} +} + +read(addr, size) { +	return read_value(addr, size); +} + +write(value, addr, size) { +	write_value(value, addr, size); +} + +adc(a, b, carry) { +	sum = a + b + carry; +	update_flags_nz(sum); +	cpu->ps.C = sum < b; +	cpu->ps.V = bit(a^b, msb-1) && bit(a^sum, msb-1); +	return sum; +} + +mul(a, b) { +	sum = a * b; +	update_flags_nz(sum); +	cpu->ps.V = bit(a^b, msb-1) && bit(a^sum, msb-1); +	return sum; +} + +div(a, b, *rem) { +	sum = a / b; +	*rem = a % b; +	update_flags_nz(sum); +	return sum; +} | 
