Mercurial > repos > blastem
changeset 2562:595719fe69f2
Implement exg, muls and mulu in new 68K core
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 25 Jan 2025 21:25:01 -0800 |
parents | 8dc8eb079584 |
children | f51d750b4d06 |
files | cpu_dsl.py m68k.cpu |
diffstat | 2 files changed, 183 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/cpu_dsl.py Sat Jan 25 19:23:37 2025 -0800 +++ b/cpu_dsl.py Sat Jan 25 21:25:01 2025 -0800 @@ -15,6 +15,8 @@ '-': 'sub', '<<': 'lsl', '>>': 'lsr', + '*': 'mulu', + '*S': 'muls', '&': 'and', '|': 'or', '^': 'xor' @@ -751,6 +753,50 @@ fmt = '\n\t{dst} = {src} & 0x8000 ? {src} | 0xFFFF0000 : {src} & 0x7FFF;' prog.lastSize = params[0] return fmt.format(src=params[1], dst=params[2]) + +def _mulsCImpl(prog, params, rawParams, flagUpdates): + p0Size = prog.paramSize(rawParams[0]) + p1Size = prog.paramSize(rawParams[1]) + destSize = prog.paramSize(rawParams[2]) + if len(params) > 3: + size = params[3] + if size == 0: + size = 8 + elif size == 1: + size = 16 + else: + size = 32 + prog.lastSize = size + else: + size = destSize + if p0Size >= size: + p0Size = size // 2 + if p1Size >= size: + p1Size = size // 2 + #TODO: Handle case in which destSize > size + return f'\n\t{params[2]} = (int{size}_t)(((int{p0Size}_t){params[0]}) * ((int{p1Size}_t){params[1]}));' + +def _muluCImpl(prog, params, rawParams, flagUpdates): + p0Size = prog.paramSize(rawParams[0]) + p1Size = prog.paramSize(rawParams[1]) + destSize = prog.paramSize(rawParams[2]) + if len(params) > 3: + size = params[3] + if size == 0: + size = 8 + elif size == 1: + size = 16 + else: + size = 32 + prog.lastSize = size + else: + size = destSize + if p0Size >= size: + p0Size = size // 2 + if p1Size >= size: + p1Size = size // 2 + #TODO: Handle case in which destSize > size + return f'\n\t{params[2]} = ((uint{p0Size}_t){params[0]}) * ((uint{p1Size}_t){params[1]});' def _getCarryCheck(prog): carryFlag = None @@ -956,6 +1002,8 @@ 'rlc': Op().addImplementation('c', 2, _rlcCImpl), 'ror': Op().addImplementation('c', 2, _rorCImpl), 'rrc': Op().addImplementation('c', 2, _rrcCImpl), + 'mulu': Op(lambda a, b: a * b).addImplementation('c', 2, _muluCImpl), + 'muls': Op().addImplementation('c', 2, _mulsCImpl), 'and': Op(lambda a, b: a & b).cBinaryOperator('&'), 'or': Op(lambda a, b: a | b).cBinaryOperator('|'), 'xor': Op(lambda a, b: a ^ b).cBinaryOperator('^'), @@ -1096,7 +1144,12 @@ def addOp(self, op): if op.op == 'case': - val = int(op.params[0], 16) if op.params[0].startswith('0x') else int(op.params[0]) + if op.params[0].startswith('0x'): + val = int(op.params[0], 16) + elif op.params[0].startswith('0b'): + val = int(op.params[0], 2) + else: + val = int(op.params[0]) self.cases[val] = self.current_case = [] self.case_locals[val] = self.current_locals = {} elif op.op == 'default': @@ -1777,6 +1830,8 @@ pass elif param.startswith('0x'): param = int(param, 16) + elif param.startswith('0b'): + param = int(param, 2) else: param = int(param) except ValueError:
--- a/m68k.cpu Sat Jan 25 19:23:37 2025 -0800 +++ b/m68k.cpu Sat Jan 25 21:25:01 2025 -0800 @@ -131,6 +131,31 @@ ocall read_16 lsl tmp 16 tmp or tmp scratch1 scratch1 + +m68k_trap + arg vector 32 + check_user_mode_swap_ssp_usp + #save PC + a7 -= 4 + scratch2 = a7 + m68k_write32_lowfirst pc + #save SR + a7 -= 2 + scratch2 = a7 + m68k_get_sr + ocall write_16 + #set supervisor bit + status |= 0x20 + #clear trace bit + status &= 0x7F + trace_pending = 0 + scratch1 = vector << 2 + m68k_read32 + pc = scratch1 + cycles 10 + m68k_prefetch + + m68k_interrupt cmp int_cycle cycles @@ -645,6 +670,102 @@ and src dregs.D dregs.D Z update_flags NZV0C0 m68k_prefetch + +1100XXX101000YYY exg_dn_dn + scratch1 = dregs.X + dregs.X = dregs.Y + dregs.Y = scratch1 + cycles 2 + m68k_prefetch + +1100XXX101001YYY exg_an_an + scratch1 = aregs.X + aregs.X = aregs.Y + aregs.Y = scratch1 + cycles 2 + m68k_prefetch + +1100XXX110001YYY exg_dn_an + scratch1 = dregs.X + dregs.X = aregs.Y + aregs.Y = scratch1 + cycles 2 + m68k_prefetch + +1100DDD011MMMRRR mulu + local a 16 + local b 16 + invalid M 1 + invalid M 7 R 5 + invalid M 7 R 6 + invalid M 7 R 7 + + m68k_fetch_src_ea M R 1 + #2-cycles per bit x 16, 2 for cleanup + cycles 34 + #popcnt + a = src & 0b1010101010101010 + a >>= 1 + b = src & 0b0101010101010101 + b += a + a = b & 0b1100110011001100 + a >>= 2 + b &= 0b0011001100110011 + b += a + a = b & 0b1111000011110000 + a >>= 4 + b &= 0b0000111100001111 + b += a + a = b & 0b1111111100000000 + a >>= 8 + b &= 0b0000000011111111 + b += a + #2 cycles per set bit + b += b + cycles b + dregs.D = src * dregs.D + update_flags NZV0C0 + m68k_prefetch + +1100DDD111MMMRRR muls + local a 16 + local b 16 + invalid M 1 + invalid M 7 R 5 + invalid M 7 R 6 + invalid M 7 R 7 + + m68k_fetch_src_ea M R 1 + #2-cycles per bit x 16, 2 for cleanup + cycles 34 + #muls timing is essentially the same as muls, but it's based on the number of 0/1 + #transitions rather than the number of 1 bits. xoring the value with itself shifted + #by one effectively sets one bit for every transition + b = src << 1 + b ^= src + #popcnt + a = b & 0b1010101010101010 + a >>= 1 + b &= 0b0101010101010101 + b += a + a = b & 0b1100110011001100 + a >>= 2 + b &= 0b0011001100110011 + b += a + a = b & 0b1111000011110000 + a >>= 4 + b &= 0b0000111100001111 + b += a + a = b & 0b1111111100000000 + a >>= 8 + b &= 0b0000000011111111 + b += a + #2 cycles per set bit + b += b + cycles b + dregs.D = src *S dregs.D + update_flags NZV0C0 + m68k_prefetch 1100DDD1ZZMMMRRR and_dn_ea invalid M 0 @@ -1876,6 +1997,12 @@ update_flags NZV0C0 m68k_prefetch +010011100100VVVV trap + local vector 32 + scratch1 = pc + vector = V + 32 + m68k_trap vector + 0100111001010RRR link a7 -= 4 scratch2 = a7