/* @(#) $Id: CpuModule_EffectiveAddress.c,v 1.3 2012-07-15 22:20:35 peschau Exp $ */ /*=========================================================================*/ /* 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" #include "fellow.h" #include "fmem.h" #include "CpuModule.h" #include "CpuModule_Internal.h" /* Calculates EA for (Ax). */ ULO cpuEA02(ULO regno) { return cpuGetAReg(regno); } /* Calculates EA for (Ax)+ */ ULO cpuEA03(ULO regno, ULO size) { ULO tmp = cpuGetAReg(regno); if (regno == 7 && size == 1) size++; cpuSetAReg(regno, tmp + size); return tmp; } /* Calculates EA for -(Ax) */ ULO cpuEA04(ULO regno, ULO size) { if (regno == 7 && size == 1) size++; cpuSetAReg(regno, cpuGetAReg(regno) - size); return cpuGetAReg(regno); } /* Calculates EA for disp16(Ax) */ ULO cpuEA05(ULO regno) { return cpuGetAReg(regno) + cpuGetNextWordSignExt(); } /* Calculates EA for disp8(Ax,Ri.size) with 68020 extended modes. */ static ULO cpuEA06Ext(UWO ext, ULO base_reg_value, ULO index_value) { ULO base_displacement; ULO outer_displacement; BOOLE index_register_suppressed = (ext & 0x0040); BOOLE base_register_suppressed = (ext & 0x0080); ULO base_displacement_size = (ext >> 4) & 3; ULO memory_indirect_action = (ext & 7); 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. */ ULO cpuEA06(ULO regno) { ULO reg_value = cpuGetAReg(regno); UWO ext = cpuGetNextWord(); ULO index_value = cpuGetReg(ext >> 15, (ext >> 12) & 7); if (!(ext & 0x0800)) { index_value = cpuSignExtWordToLong((UWO)index_value); } 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); } } return reg_value + index_value + cpuSignExtByteToLong((UBY)ext); } /* Calculates EA for xxxx.W */ ULO cpuEA70(void) { return cpuGetNextWordSignExt(); } /* Calculates EA for xxxxxxxx.L */ ULO cpuEA71(void) { return cpuGetNextLong(); } /// /// Calculates EA for disp16(PC) /// /// Address ULO cpuEA72(void) { ULO pc_tmp = cpuGetPC(); return pc_tmp + cpuGetNextWordSignExt(); } /// /// Calculates EA for disp8(PC,Ri.size). Calls cpuEA06Ext() to calculate extended 68020 modes. /// /// Address ULO cpuEA73(void) { ULO reg_value = cpuGetPC(); UWO ext = cpuGetNextWord(); ULO index_value = cpuGetReg(ext >> 15, (ext >> 12) & 0x7); if (!(ext & 0x0800)) { index_value = cpuSignExtWordToLong((UWO)index_value); } 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); } } return reg_value + index_value + cpuSignExtByteToLong((UBY)ext); }