home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * m_cpumem.c
- * Copyright © 1992 Niklas Röjemo
- */
-
- #include "mnemonics.h"
- #include "error.h"
- #include "option.h"
- #include "put.h"
- #include "input.h"
- #include "global.h"
- #include "expr.h"
- #include "code.h"
- #include "area.h"
- #include "lit.h"
- #include "get.h"
- #include "fix.h"
- #include "expr.h"
-
-
- static void dstmem(unsigned int ir)
- {
- int op;
- BOOL trans = FALSE;
- BOOL pre;
- Value offset;
- op = getCpuReg();
- ir |= DST_OP(op);
- skipblanks();
- if(inputLook() == ',') { inputSkip(); skipblanks(); }
- else error(ErrorError,TRUE,"Inserting missing comma before address.");
- switch(inputLook()) {
- case '[': /* ldr reg,[ */
- { BOOL up = TRUE;
- inputSkip();
- skipblanks();
- op = getCpuReg(); /* Base register */
- ir |= LHS_OP(op);
- skipblanks();
- if(inputLook() == ']') { pre = FALSE; inputSkip(); skipblanks(); }
- else pre = TRUE;
- if(inputLook() == ',') { /* either [base,XX] or [base],XX */
- inputSkip();
- skipblanks();
- if(inputLook() == '+') { inputSkip(); skipblanks(); }
- else if(inputLook() == '-') { inputSkip(); skipblanks(); up = FALSE;}
- if(inputLook() == '#') {
- inputSkip();
- exprBuild();
- if(!up) codeOperator(Op_neg);
- offset = exprEval(ValueInt |ValueCode|ValueLateLabel);
- switch(offset.Tag) {
- case ValueInt:
- ir = fixCpuOffset(inputLineNo,ir,offset.ValueInt.i);
- break;
- case ValueCode: case ValueLateLabel:
- relocCpuOffset(ir,offset);
- break;
- default:
- error(ErrorError,TRUE,"Illegal offset expression.");
- break;
- }
- /* UP_FLAG is fixed in fixCpuOffset */
- } else {
- ir |= REG_FLAG;
- ir = getRhs(TRUE,ir); /* Can only be Reg {,shiftop {#shift}} */
- if(up)
- ir |= UP_FLAG; /* !! Fixed !! */
- }
- skipblanks();
- } else { /* [base] if this way */
- ir |= UP_FLAG; /* 0 nicer than -0 */
- if(pre)
- error(ErrorError,TRUE,"Illegal character '%c' after base.",inputLook());
- }
- if(pre) {
- if(inputLook() == ']') { inputSkip(); skipblanks(); }
- else error(ErrorError,TRUE,"Inserting missing ] after address.");
- }
- if(inputLook() == '!') {
- if(pre) ir |= WB_FLAG;
- else error(ErrorError,TRUE,"Writeback not allowed together with post-(inc/dec)rement.");
- inputSkip();
- skipblanks();
- }
- if(pre) {
- ir |= PRE_FLAG;
- if(trans)
- error(ErrorError,TRUE,"Translate not allowed together with pre-(inc/dec)rement.");
- }
- } break;
- case '=':
- if(ir & 0x00100000) { /* only allowed for ldr */
- ir |= PRE_FLAG | LHS_OP(15);
- inputSkip();
- exprBuild();
- litInt(4,exprEval(ValueInt | ValueString|ValueCode|ValueLateLabel));
- } else {
- error(ErrorError,FALSE,"You can't store into a constant!.");
- } break;
- default: /* ldr reg,label */
- ir |= PRE_FLAG | LHS_OP(15);
- exprBuild();
- codePosition(areaCurrent);
- codeOperator(Op_sub);
- codeInt(8);
- codeOperator(Op_sub);
- offset = exprEval(ValueInt |ValueCode|ValueLateLabel);
- switch(offset.Tag) {
- case ValueInt:
- ir = fixCpuOffset(inputLineNo,ir,offset.ValueInt.i);
- break;
- case ValueCode: case ValueLateLabel:
- relocCpuOffset(ir,offset);
- break;
- default:
- error(ErrorError,TRUE,"Illegal address expression.");
- break;
- }
- }
- putIns(ir);
- }
-
- void m_ldr(unsigned int cc)
- {
- dstmem(cc|0x04100000);
- }
-
- void m_str(unsigned int cc)
- {
- dstmem(cc|0x04000000);
- }
-
- static void dstreglist(unsigned int ir)
- {
- int op,low,high,c;
- Value mask;
- op = getCpuReg();
- ir |= BASE_MULTI(op);
- skipblanks();
- if(inputLook() == '!') { inputSkip(); ir |= WB_FLAG; skipblanks();}
- if(inputLook() == ',') { inputSkip(); skipblanks();}
- else error(ErrorError,TRUE,"Inserting missing comma before reglist.");
- if(inputLook() == '#') { /* constant */
- exprBuild();
- mask = exprEval(ValueInt | ValueCode|ValueLateLabel);
- switch(mask.Tag) {
- case ValueInt:
- ir |= fixMask(inputLineNo,mask.ValueInt.i);
- break;
- case ValueCode: case ValueLateLabel:
- relocMask(mask);
- break;
- default:
- error(ErrorError,TRUE,"Illegal mask expression.");
- break;
- }
- } else {
- if(inputLook() == '{') { inputSkip(); }
- else error(ErrorError,TRUE,"Inserting missing '{' before reglist.");
- op = 0;
- do {
- skipblanks();
- low = getCpuReg();
- skipblanks();
- switch(c=inputLook()) {
- case '-':
- inputSkip();
- skipblanks();
- high = getCpuReg();
- skipblanks();
- if(low>high) {
- error(ErrorInfo,TRUE,"Register interval in wrong order r%d-r%d.",low,high);
- c = low; low = high; high = c;
- }
- break;
- case ',': case '}':
- high = low;
- break;
- default: error(ErrorError,TRUE,"Illegal character '%c' in register list.",c);
- }
- if(1<<low < op)
- error(ErrorInfo,TRUE,"Registers in wrong order.");
- if( ((1<<(high+1))-(1<<low)) & op)
- error(ErrorInfo,TRUE,"Register occures more than once in register list.");
- op |= (1<<(high+1))-(1<<low);
- } while((c=inputGet()) == ',');
- if(c != '}') { inputUnGet(c); error(ErrorError,TRUE,"Inserting missing '}' after reglist."); }
- ir |= op;
- }
- skipblanks();
- if(inputLook() == '^') {
- inputSkip();
- if(ir & WB_FLAG && !(ir & (1<<15)))
- error(ErrorInfo,TRUE,"Writeback together with force user.");
- ir |= FORCE_FLAG;
- skipblanks();
- }
- putIns(ir);
- }
-
- void m_ldm(unsigned int cc)
- {
- dstreglist(cc|0x08100000);
- }
-
- void m_stm(unsigned int cc)
- {
- dstreglist(cc|0x08000000);
- }
-
- void m_swp(unsigned int cc)
- {
- int ir = cc | 0x01000090;
- ir |= DST_OP(getCpuReg());
- skipblanks();
- if(inputLook() == ',') {inputSkip(); skipblanks();}
- else error(ErrorError,TRUE,"Inserting a comma after dst.");
- ir |= RHS_OP(getCpuReg()); /* Note wrong order swp dst,rhs,[lsh] */
- skipblanks();
- if(inputLook() == ',') {inputSkip(); skipblanks();}
- else error(ErrorError,TRUE,"Inserting a comma after lhs.");
- if(inputLook() == '[') {inputSkip(); skipblanks();}
- else error(ErrorError,TRUE,"Inserting missing '['.");
- ir |= LHS_MUL(getCpuReg());
- skipblanks();
- if(inputLook() == ']') {inputSkip(); skipblanks();}
- else error(ErrorError,TRUE,"Inserting missing ']'.");
- putIns(ir);
- }
-