home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * fix.c
- * Copyright © 1992 Niklas Röjemo
- */
-
- #include "error.h"
- #include "help_cpu.h"
- #include "fix.h"
- #include "global.h"
- #include "m_cpu.h"
- #include "m_fpu.h"
- #include "option.h"
-
- WORD fixShiftImm(int lineno, WORD shiftop, int shift)
- {
- switch(shiftop) {
- case LSL:
- if(shift<0 || shift>31) {
- errorLine(lineno,ErrorError,TRUE,"Illegal immediate shift %d.",shift);
- shift = 1;
- } break;
- case LSR:
- if(shift == 0) shiftop = LSL;
- else if(shift<1 || shift>32) {
- errorLine(lineno,ErrorError,TRUE,"Illegal immediate shift %d.",shift);
- shift = 1;
- } break;
- case ASR:
- if(shift == 0) shiftop = LSL;
- else if(shift<1 || shift>32) {
- errorLine(lineno,ErrorError,TRUE,"Illegal immediate shift %d.",shift);
- shift = 1;
- } break;
- case ROR:
- if(shift == 0) shiftop = LSL;
- else if(shift<1 || shift>31) {
- errorLine(lineno,ErrorError,TRUE,"Illegal immediate shift %d.",shift);
- shift = 1;
- } break;
- default:
- errorLine(lineno,ErrorSerious,FALSE,"Internal error in getshift.");
- }
- return SHIFT_IMM(shift) | SHIFT_OP(shiftop);
- }
-
- extern int pedantic;
-
- WORD fixImm8s4(int lineno, WORD ir, int im)
- {
- int i8s4 = help_cpuImm8s4(im);
- if(i8s4 == -1) { /* Not a legal immediate */
- switch(ir & M_MNEM) { /* try changing opcode */
- case M_ADD:
- if((i8s4 = help_cpuImm8s4(-im)) != -1) {
- ir = (ir & ~M_MNEM) | M_SUB;
- if(pedantic) errorLine(lineno,ErrorInfo,TRUE,"Changing add r_,r_,#%d to sub r_,r_,#%d.",im,-im);
- } break;
- case M_SUB:
- if((i8s4 = help_cpuImm8s4(-im)) != -1) {
- ir = (ir & ~M_MNEM) | M_ADD;
- if(pedantic) errorLine(lineno,ErrorInfo,TRUE,"Changing sub r_,r_,#%d to add r_,r_,#%d.",im,-im);
- } break;
- case M_ADC:
- if((i8s4 = help_cpuImm8s4(-im)) != -1) {
- ir = (ir & ~M_MNEM) | M_SBC;
- if(pedantic) errorLine(lineno,ErrorInfo,TRUE,"Changing adc r_,r_,#%d to sbc r_,r_,#%d.",im,-im);
- } break;
- case M_SBC:
- if((i8s4 = help_cpuImm8s4(-im)) != -1) {
- ir = (ir & ~M_MNEM) | M_ADC;
- if(pedantic) errorLine(lineno,ErrorInfo,TRUE,"Changing sbc r_,r_,#%d to adc r_,r_,#%d.",im,-im);
- } break;
- case M_CMP:
- if((i8s4 = help_cpuImm8s4(-im)) != -1) {
- ir = (ir & ~M_MNEM) | M_CMN;
- if(pedantic) errorLine(lineno,ErrorInfo,TRUE,"Changing cmp r_,#%d to cmn r_,r_,#%d.",im,-im);
- } break;
- case M_CMN:
- if((i8s4 = help_cpuImm8s4(-im)) != -1) {
- ir = (ir & ~M_MNEM) | M_CMP;
- if(pedantic) errorLine(lineno,ErrorInfo,TRUE,"Changing cmn r_,#%d to cmp r_,#%d.",im,-im);
- } break;
- case M_MOV:
- if((i8s4 = help_cpuImm8s4(~im)) != -1) {
- ir = (ir & ~M_MNEM) | M_MVN;
- if(pedantic) errorLine(lineno,ErrorInfo,TRUE,"Changing mov r_,#%d to mvn r_,#%d.",im,~im);
- } break;
- case M_MVN:
- if((i8s4 = help_cpuImm8s4(~im)) != -1) {
- ir = (ir & ~M_MNEM) | M_MOV;
- if(pedantic) errorLine(lineno,ErrorInfo,TRUE,"Changing mvn r_,#%d to mov r_,#%d.",im,~im);
- } break;
- case M_AND:
- if((i8s4 = help_cpuImm8s4(~im)) != -1) {
- ir = (ir & ~M_MNEM) | M_BIC;
- if(pedantic) errorLine(lineno,ErrorInfo,TRUE,"Changing and r_,r_,#0x%x to bic r_,r_,#0x%x.",im,~im);
- } break;
- case M_BIC:
- if((i8s4 = help_cpuImm8s4(~im)) != -1) {
- ir = (ir & ~M_MNEM) | M_AND;
- if(pedantic) errorLine(lineno,ErrorInfo,TRUE,"Changing bic r_,r_,#0x%x to and r_,r_,#0x%x.",im,~im);
- } break;
- }
- }
- if(i8s4 == -1) {
- errorLine(lineno,ErrorError,TRUE,"Illegal immediate constant %d (0x%08x).",im,im);
- i8s4 = 0;
- }
- return ir|i8s4;
- }
-
- WORD fixImmFloat(int lineno, WORD ir, FLOAT im)
- {
- int f = fpuImm(im);
- if(f == -1) { /* Not a legal float immediate */
- switch(ir & M_FMNEM) { /* try changing opcode */
- case M_ADF:
- if((f = fpuImm(-im)) != -1) {
- ir = (ir & ~M_FMNEM) | M_SUF;
- if(pedantic) errorLine(lineno,ErrorInfo,TRUE,"Changing adf f_,f_,#%.1f to suf f_,f_,#%.1f.",im,-im);
- } break;
- case M_SUF:
- if((f = fpuImm(-im)) != -1) {
- ir = (ir & ~M_FMNEM) | M_ADF;
- if(pedantic) errorLine(lineno,ErrorInfo,TRUE,"Changing suf f_,f_,#%.1f to adf f_,f_,#%.1f.",im,-im);
- } break;
- case M_MVF:
- if((f = fpuImm(-im)) != -1) {
- ir = (ir & ~M_FMNEM) | M_MNF;
- if(pedantic) errorLine(lineno,ErrorInfo,TRUE,"Changing mvf f_,#%.1f to mnf f_,#%.1f.",im,-im);
- } break;
- case M_MNF:
- if((f = fpuImm(-im)) != -1) {
- ir = (ir & ~M_FMNEM) | M_MVF;
- if(pedantic) errorLine(lineno,ErrorInfo,TRUE,"Changing mnf f_,#%.1f to mvf f_,#%.1f.",im,-im);
- } break;
- case M_CMF&M_FMNEM:
- if((f = fpuImm(-im)) != -1) {
- ir = (ir & ~M_FMNEM) | M_CNF;
- if(pedantic) errorLine(lineno,ErrorInfo,TRUE,"Changing cmf f_,#%.1f to cnf f_,#%.1f.",im,-im);
- } break;
- case M_CNF&M_FMNEM:
- if((f = fpuImm(-im)) != -1) {
- ir = (ir & ~M_FMNEM) | M_CMF;
- if(pedantic) errorLine(lineno,ErrorInfo,TRUE,"Changing cnf f_,#%.1f to cmf f_,#%.1f.",im,-im);
- } break;
- case (M_CMF|EXEPTION_BIT)&M_FMNEM:
- if((f = fpuImm(-im)) != -1) {
- ir = (ir & ~M_FMNEM) | M_CNF|EXEPTION_BIT;
- if(pedantic) errorLine(lineno,ErrorInfo,TRUE,"Changing cmfe f_,#%.1f to cnfe f_,#%.1f.",im,-im);
- } break;
- case (M_CNF|EXEPTION_BIT)&M_FMNEM:
- if((f = fpuImm(-im)) != -1) {
- ir = (ir & ~M_FMNEM) | M_CMF|EXEPTION_BIT;
- if(pedantic) errorLine(lineno,ErrorInfo,TRUE,"Changing cnfe f_,#%.1f to cmfe f_,#%.1f.",im,-im);
- } break;
- }
- }
- if(f == -1) {
- errorLine(lineno,ErrorError,TRUE,"Illegal immediate constant %g.",im);
- f = 0;
- }
- return ir|f;
- }
-
- WORD fixAdr(int lineno, WORD ir, int im) /* !!! mov and mvn should be possible */
- {
- int i8s4;
- if(im<0) {
- ir |= 0x00400000; /* sub */
- im = -im;
- } else
- ir |= 0x00800000; /* add */
- i8s4 = help_cpuImm8s4(im);
- if(i8s4 == -1)
- errorLine(lineno,ErrorError,TRUE,"Offset %d (0x%08x) is illegal for adr.",im,im);
- else
- ir |= i8s4;
- return ir;
- }
-
- WORD fixSwi(int lineno, int im)
- {
- if((im & 0xffffff) != im)
- errorLine(lineno,ErrorError,TRUE,"Illegal swi number %d(0x%08x).",im,im);
- return im&0xffffff;
- }
-
- WORD fixBranch(int lineno, int im)
- {
- if(im & 3)
- errorLine(lineno,ErrorError,TRUE,"Branch value is not a multiple of four.");
- return (im>>2)&0xffffff;
- }
-
- WORD fixCopOffset(int lineno, WORD ir, int offset)
- {
- BOOL up = TRUE;
- if(offset<0) { offset = -offset; up = FALSE; }
- if(offset&3) errorLine(lineno,ErrorError,TRUE,"Offset %d is not a word offset.",offset);
- if(offset>1020) errorLine(lineno,ErrorError,TRUE,"Offset %d is to large.",offset);
- ir |= (offset>>2)&0xff;
- if(up) ir |= UP_FLAG;
- return ir;
- }
-
- WORD fixCpuOffset(int lineno, WORD ir, int offset)
- {
- BOOL up = TRUE;
- if(offset<0) { offset = -offset; up = FALSE; }
- if(offset>4095) errorLine(lineno,ErrorError,TRUE,"Offset %d is to large.",offset);
- ir |= offset&0xfff;
- if(up) ir |= UP_FLAG;
- return ir;
- }
-
- WORD fixMask(int lineno, int mask)
- {
- if(mask < 0 || mask >0xffff)
- errorLine(lineno,ErrorError,TRUE,"Illegal value for register mask 0x%x.",mask);
- return mask&0xffff;
- }
-
- WORD fixInt(int lineno, int size, int value)
- {
- switch(size) {
- case 1:
- if(value<-128 || value>256) {
- errorLine(lineno,ErrorError,TRUE,"Expression %d to big for 8 bits.",value);
- value &= 0xff;
- } break;
- case 2:
- if(value<-32768 || value>65536) {
- errorLine(lineno,ErrorError,TRUE,"Expression %d to big for 16 bits.",value);
- value &= 0xffff;
- } break;
- case 4:
- break;
- default:
- errorLine(lineno,ErrorSerious,TRUE,"Internal fixInt: Size %d is not legal.",size);
- }
- return value;
- }
-