summaryrefslogtreecommitdiff
path: root/sdas/as8xcxxx/ds8adr.c
diff options
context:
space:
mode:
authorXavier ASUS <xavi92psx@gmail.com>2019-10-18 00:31:54 +0200
committerXavier ASUS <xavi92psx@gmail.com>2019-10-18 00:31:54 +0200
commit268a53de823a6750d6256ee1fb1e7707b4b45740 (patch)
tree42c1799a9a82b2f7d9790ee9fe181d72a7274751 /sdas/as8xcxxx/ds8adr.c
downloadsdcc-gas-268a53de823a6750d6256ee1fb1e7707b4b45740.tar.gz
sdcc-3.9.0 fork implementing GNU assembler syntax
This fork aims to provide better support for stm8-binutils
Diffstat (limited to 'sdas/as8xcxxx/ds8adr.c')
-rw-r--r--sdas/as8xcxxx/ds8adr.c249
1 files changed, 249 insertions, 0 deletions
diff --git a/sdas/as8xcxxx/ds8adr.c b/sdas/as8xcxxx/ds8adr.c
new file mode 100644
index 0000000..3575707
--- /dev/null
+++ b/sdas/as8xcxxx/ds8adr.c
@@ -0,0 +1,249 @@
+/* ds8adr.c */
+
+/*
+ * Copyright (C) 1998-2009 Alan R. Baldwin
+ *
+ * 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 3 of the License, 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, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio 44240
+ *
+ * This Assember Ported by
+ * jhartman at compuserve dot com
+ * noice at noicedebugger dot com
+ *
+ * Modified from i51pst.c
+ * Bill McKinnon
+ * w_mckinnon at conknet dot com
+ *
+ */
+
+#include "asxxxx.h"
+#include "ds8.h"
+
+
+struct adsym reg51[] = { /* R0 thru R7 registers */
+ { "R0", R0 },
+ { "R1", R1 },
+ { "R2", R2 },
+ { "R3", R3 },
+ { "R4", R4 },
+ { "R5", R5 },
+ { "R6", R6 },
+ { "R7", R7 },
+ { "A", A },
+ { "DPTR", DPTR },
+ { "PC", PC },
+ { "C", C },
+ { "AB", AB },
+ { "", 0x00 }
+};
+
+/* Classify argument as to address mode */
+int
+addr(struct expr *esp)
+{
+ int c;
+ unsigned int rd;
+
+ if ((c = getnb()) == '#') {
+ /* Immediate mode */
+ expr(esp, 0);
+ esp->e_mode = S_IMMED;
+ }
+ else if (c == '@') {
+ /* choices are @R0, @R1, @DPTR, @A+PC, @A+DPTR */
+ switch (reg()) {
+ case R0:
+ esp->e_mode = S_AT_R;
+ esp->e_addr = R0;
+ break;
+ case R1:
+ esp->e_mode = S_AT_R;
+ esp->e_addr = R1;
+ break;
+ case DPTR:
+ esp->e_mode = S_AT_DP;
+ esp->e_addr = DPTR;
+ break;
+ case A:
+ if (getnb() == '+') {
+ rd = reg();
+ if (rd == PC) {
+ esp->e_mode = S_AT_APC;
+ esp->e_addr = 0;
+ } else if (rd == DPTR) {
+ esp->e_mode = S_AT_ADP;
+ esp->e_addr = 0;
+ } else {
+ aerr();
+ }
+ } else
+ aerr();
+ break;
+ }
+
+ esp->e_flag = 0;
+ esp->e_base.e_ap = NULL;
+ }
+ else if (c == '*') {
+ if ((c = getnb()) == '/') {
+ /* Force inverted bit */
+ expr(esp, 0);
+ esp->e_mode = S_NOT_BIT;
+ } else {
+ unget(c);
+ /* Force direct page */
+ expr(esp, 0);
+ esp->e_mode = S_DIR;
+ }
+ if (esp->e_addr & ~0xFF)
+ err('d');
+ }
+ else if (c == '/') {
+ /* Force inverted bit */
+ expr(esp, 0);
+ esp->e_mode = S_NOT_BIT;
+ }
+ else {
+ unget(c);
+
+ /* try for register: A, AB, R0-R7, DPTR, PC, Cy */
+ if ((esp->e_addr = admode(reg51)) != -1) {
+ switch (esp->e_addr) {
+ case A:
+ esp->e_mode = S_A;
+ break;
+ case AB:
+ esp->e_mode = S_RAB;
+ break;
+ case DPTR:
+ esp->e_mode = S_DPTR;
+ break;
+ case PC:
+ esp->e_mode = S_PC;
+ break;
+ case C:
+ esp->e_mode = S_C;
+ break;
+ default:
+ /* R0-R7 */
+ esp->e_mode = S_REG;
+ }
+ } else {
+ /* Must be an expression */
+ esp->e_addr = 0; /* Vasiliy Petrov */
+ expr(esp, 0);
+ if ((!esp->e_flag)
+ && (esp->e_base.e_ap==NULL)
+ && !(esp->e_addr & ~0xFF)) {
+ esp->e_mode = S_DIR;
+ } else {
+ esp->e_mode = S_EXT;
+ }
+ }
+ }
+ return (esp->e_mode);
+}
+
+/*
+ * Enter admode() to search a specific addressing mode table
+ * for a match. Return the addressing value on a match or
+ * -1 for no match.
+ */
+int
+admode(struct adsym *sp)
+{
+ char *ptr;
+ int i;
+
+ unget(getnb());
+ i = 0;
+ while ( *(ptr = &sp[i].a_str[0]) ) {
+ if (srch(ptr)) {
+ return(sp[i].a_val);
+ }
+ i++;
+ }
+ return(-1);
+}
+
+/*
+ * srch --- does string match ?
+ */
+int
+srch(char *str)
+{
+ char *ptr;
+ ptr = ip;
+
+ while (*ptr && *str) {
+ if(ccase[*ptr & 0x007F] != ccase[*str & 0x007F])
+ break;
+ ptr++;
+ str++;
+ }
+ if (ccase[*ptr & 0x007F] == ccase[*str & 0x007F]) {
+ ip = ptr;
+ return(1);
+ }
+
+ if (!*str)
+ if (any(*ptr," \t\n,];")) {
+ ip = ptr;
+ return(1);
+ }
+ return(0);
+}
+
+/*
+ * any --- does str contain c?
+ */
+int
+any(int c, char *str)
+{
+ while (*str)
+ if(*str++ == c)
+ return(1);
+ return(0);
+}
+
+/*
+ * Read a register name. Return register value, -1 if no register found
+ */
+int
+reg(void)
+{
+ struct mne *mp;
+ char id[NCPS];
+
+ getid(id, -1);
+ if ((mp = mlookup(id))==NULL) {
+ aerr();
+ return (-1);
+ }
+ switch (mp->m_type) {
+ case S_A:
+ case S_AB:
+ case S_DPTR:
+ case S_PC:
+ case S_REG:
+ return ((int) mp->m_valu);
+
+ default:
+ return (-1);
+ }
+}