2013-02-06 04:11:41 +00:00
|
|
|
/*=========================================================================*/
|
|
|
|
/* Fellow */
|
|
|
|
/* CPU 68k effective address calculation functions */
|
|
|
|
/* */
|
|
|
|
/* Author: Petter Schau */
|
|
|
|
/* */
|
|
|
|
/* */
|
|
|
|
/* Copyright (C) 1991, 1992, 1996 Free Software Foundation, Inc. */
|
|
|
|
/* */
|
|
|
|
/* This program is free software; you can redistribute it and/or modify */
|
|
|
|
/* it under the terms of the GNU General Public License as published by */
|
|
|
|
/* the Free Software Foundation; either version 2, or (at your option) */
|
|
|
|
/* any later version. */
|
|
|
|
/* */
|
|
|
|
/* This program is distributed in the hope that it will be useful, */
|
|
|
|
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
|
|
|
|
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
|
|
|
|
/* GNU General Public License for more details. */
|
|
|
|
/* */
|
|
|
|
/* You should have received a copy of the GNU General Public License */
|
|
|
|
/* along with this program; if not, write to the Free Software Foundation, */
|
|
|
|
/* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
|
|
|
/*=========================================================================*/
|
|
|
|
|
|
|
|
#include "defs.h"
|
2016-05-16 17:45:32 +00:00
|
|
|
#include "CpuModule_Memory.h"
|
2013-02-06 04:11:41 +00:00
|
|
|
|
|
|
|
#include "CpuModule.h"
|
|
|
|
#include "CpuModule_Internal.h"
|
|
|
|
|
|
|
|
/* Calculates EA for (Ax). */
|
2023-10-05 22:47:48 +00:00
|
|
|
uint32_t cpuEA02(uint32_t regno)
|
2013-02-06 04:11:41 +00:00
|
|
|
{
|
|
|
|
return cpuGetAReg(regno);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Calculates EA for (Ax)+ */
|
2023-10-05 22:47:48 +00:00
|
|
|
uint32_t cpuEA03(uint32_t regno, uint32_t size)
|
2013-02-06 04:11:41 +00:00
|
|
|
{
|
2023-10-05 22:47:48 +00:00
|
|
|
uint32_t tmp = cpuGetAReg(regno);
|
2013-02-06 04:11:41 +00:00
|
|
|
if (regno == 7 && size == 1) size++;
|
|
|
|
cpuSetAReg(regno, tmp + size);
|
|
|
|
return tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Calculates EA for -(Ax) */
|
2023-10-05 22:47:48 +00:00
|
|
|
uint32_t cpuEA04(uint32_t regno, uint32_t size)
|
2013-02-06 04:11:41 +00:00
|
|
|
{
|
|
|
|
if (regno == 7 && size == 1) size++;
|
|
|
|
cpuSetAReg(regno, cpuGetAReg(regno) - size);
|
|
|
|
return cpuGetAReg(regno);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Calculates EA for disp16(Ax) */
|
2023-10-05 22:47:48 +00:00
|
|
|
uint32_t cpuEA05(uint32_t regno)
|
2013-02-06 04:11:41 +00:00
|
|
|
{
|
|
|
|
return cpuGetAReg(regno) + cpuGetNextWordSignExt();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Calculates EA for disp8(Ax,Ri.size) with 68020 extended modes. */
|
2023-10-05 22:47:48 +00:00
|
|
|
static uint32_t cpuEA06Ext(uint16_t ext, uint32_t base_reg_value, uint32_t index_value)
|
2013-02-06 04:11:41 +00:00
|
|
|
{
|
2023-10-05 22:47:48 +00:00
|
|
|
uint32_t base_displacement;
|
|
|
|
uint32_t outer_displacement;
|
2013-02-06 04:11:41 +00:00
|
|
|
BOOLE index_register_suppressed = (ext & 0x0040);
|
|
|
|
BOOLE base_register_suppressed = (ext & 0x0080);
|
2023-10-05 22:47:48 +00:00
|
|
|
uint32_t base_displacement_size = (ext >> 4) & 3;
|
|
|
|
uint32_t memory_indirect_action = (ext & 7);
|
2013-02-06 04:11:41 +00:00
|
|
|
|
|
|
|
if (memory_indirect_action == 4
|
|
|
|
|| (memory_indirect_action > 4 && index_register_suppressed))
|
|
|
|
{
|
|
|
|
cpuThrowIllegalInstructionException(TRUE); /* Illegal instruction */
|
|
|
|
// Never returns
|
|
|
|
}
|
|
|
|
|
|
|
|
if (index_register_suppressed)
|
|
|
|
{
|
|
|
|
index_value = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (base_register_suppressed)
|
|
|
|
{
|
|
|
|
base_reg_value = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (base_displacement_size)
|
|
|
|
{
|
|
|
|
case 0: /* Reserved */
|
|
|
|
cpuThrowIllegalInstructionException(TRUE); /* Illegal instruction */
|
|
|
|
break;
|
|
|
|
case 1: /* Null base displacement */
|
|
|
|
base_displacement = 0;
|
|
|
|
break;
|
|
|
|
case 2: /* Word base displacement */
|
|
|
|
base_displacement = cpuGetNextWordSignExt();
|
|
|
|
break;
|
|
|
|
case 3: /* Long base displacement */
|
|
|
|
base_displacement = cpuGetNextLong();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (memory_indirect_action)
|
|
|
|
{
|
|
|
|
case 0: /* No memory indirect action */
|
|
|
|
return base_reg_value + base_displacement + index_value;
|
|
|
|
case 1: /* Indirect preindexed with null outer displacement */
|
|
|
|
return memoryReadLong(base_reg_value + base_displacement + index_value);
|
|
|
|
case 2: /* Indirect preindexed with word outer displacement */
|
|
|
|
outer_displacement = cpuGetNextWordSignExt();
|
|
|
|
return memoryReadLong(base_reg_value + base_displacement + index_value) + outer_displacement;
|
|
|
|
case 3: /* Indirect preindexed with long outer displacement */
|
|
|
|
outer_displacement = cpuGetNextLong();
|
|
|
|
return memoryReadLong(base_reg_value + base_displacement + index_value) + outer_displacement;
|
|
|
|
case 5: /* Indirect postindexed with null outer displacement, reserved for index register suppressed */
|
|
|
|
return memoryReadLong(base_reg_value + base_displacement) + index_value;
|
|
|
|
case 6: /* Indirect postindexed with word outer displacement, reserved for index register suppressed */
|
|
|
|
outer_displacement = cpuGetNextWordSignExt();
|
|
|
|
return memoryReadLong(base_reg_value + base_displacement) + index_value + outer_displacement;
|
|
|
|
case 7: /* Indirect postindexed with long outer displacement, reserved for index register suppressed */
|
|
|
|
outer_displacement = cpuGetNextLong();
|
|
|
|
return memoryReadLong(base_reg_value + base_displacement) + index_value + outer_displacement;
|
|
|
|
}
|
|
|
|
return 0; /* Should never come here. */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Calculates EA for disp8(Ax,Ri.size), calls cpuEA06Ext() for 68020 extended modes. */
|
2023-10-05 22:47:48 +00:00
|
|
|
uint32_t cpuEA06(uint32_t regno)
|
2013-02-06 04:11:41 +00:00
|
|
|
{
|
2023-10-05 22:47:48 +00:00
|
|
|
uint32_t reg_value = cpuGetAReg(regno);
|
|
|
|
uint16_t ext = cpuGetNextWord();
|
|
|
|
uint32_t index_value = cpuGetReg(ext >> 15, (ext >> 12) & 7);
|
2013-02-06 04:11:41 +00:00
|
|
|
if (!(ext & 0x0800))
|
|
|
|
{
|
2023-10-05 22:47:48 +00:00
|
|
|
index_value = cpuSignExtWordToLong((uint16_t)index_value);
|
2013-02-06 04:11:41 +00:00
|
|
|
}
|
|
|
|
if (cpuGetModelMajor() >= 2)
|
|
|
|
{
|
|
|
|
index_value = index_value << ((ext >> 9) & 3); /* Scaling index value */
|
|
|
|
if (ext & 0x0100) /* Full extension word */
|
|
|
|
{
|
|
|
|
return cpuEA06Ext(ext, reg_value, index_value);
|
|
|
|
}
|
|
|
|
}
|
2023-10-05 22:47:48 +00:00
|
|
|
return reg_value + index_value + cpuSignExtByteToLong((uint8_t)ext);
|
2013-02-06 04:11:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Calculates EA for xxxx.W */
|
2023-10-05 22:47:48 +00:00
|
|
|
uint32_t cpuEA70()
|
2013-02-06 04:11:41 +00:00
|
|
|
{
|
|
|
|
return cpuGetNextWordSignExt();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Calculates EA for xxxxxxxx.L */
|
2023-10-05 22:47:48 +00:00
|
|
|
uint32_t cpuEA71()
|
2013-02-06 04:11:41 +00:00
|
|
|
{
|
|
|
|
return cpuGetNextLong();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Calculates EA for disp16(PC)
|
|
|
|
/// </summary>
|
|
|
|
/// <returns>Address</returns>
|
2023-10-05 22:47:48 +00:00
|
|
|
uint32_t cpuEA72()
|
2013-02-06 04:11:41 +00:00
|
|
|
{
|
2023-10-05 22:47:48 +00:00
|
|
|
uint32_t pc_tmp = cpuGetPC();
|
2013-02-06 04:11:41 +00:00
|
|
|
return pc_tmp + cpuGetNextWordSignExt();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Calculates EA for disp8(PC,Ri.size). Calls cpuEA06Ext() to calculate extended 68020 modes.
|
|
|
|
/// </summary>
|
|
|
|
/// <returns>Address</returns>
|
2023-10-05 22:47:48 +00:00
|
|
|
uint32_t cpuEA73()
|
2013-02-06 04:11:41 +00:00
|
|
|
{
|
2023-10-05 22:47:48 +00:00
|
|
|
uint32_t reg_value = cpuGetPC();
|
|
|
|
uint16_t ext = cpuGetNextWord();
|
|
|
|
uint32_t index_value = cpuGetReg(ext >> 15, (ext >> 12) & 0x7);
|
2013-02-06 04:11:41 +00:00
|
|
|
if (!(ext & 0x0800))
|
|
|
|
{
|
2023-10-05 22:47:48 +00:00
|
|
|
index_value = cpuSignExtWordToLong((uint16_t)index_value);
|
2013-02-06 04:11:41 +00:00
|
|
|
}
|
|
|
|
if (cpuGetModelMajor() >= 2)
|
|
|
|
{
|
|
|
|
index_value = index_value << ((ext >> 9) & 0x3); // Scaling index value
|
|
|
|
if (ext & 0x0100) // Full extension word
|
|
|
|
{
|
|
|
|
return cpuEA06Ext(ext, reg_value, index_value);
|
|
|
|
}
|
|
|
|
}
|
2023-10-05 22:47:48 +00:00
|
|
|
return reg_value + index_value + cpuSignExtByteToLong((uint8_t)ext);
|
2013-02-06 04:11:41 +00:00
|
|
|
}
|