int stm32_adc_setup(void) { static bool initialized = false; uint8_t channel[1] = {10}; struct adc_dev_s *adc; int rv; if (initialized) { return OK; } ainfo("INFO: Initializing ADC12_IN10\n"); stm32_configgpio(GPIO_ADC12_IN10); if ((adc = stm32_adcinitialize(1, channel, 1)) == NULL) { aerr("ERROR: Failed to get adc interface\n"); return -ENODEV; } if ((rv = adc_register("/dev/adc0", adc)) < 0) { aerr("ERROR: adc_register failed: %d\n", rv); return rv; } initialized = true; ainfo("INFO: ADC12_IN10 initialized succesfully\n"); return OK; }
int stm32_pwm_setup(void) { static bool initialized = false; struct pwm_lowerhalf_s *pwm; int ret; /* Have we already initialized? */ if (!initialized) { /* Call stm32_pwminitialize() to get an instance of the PWM interface */ pwm = stm32_pwminitialize(STM3240G_EVAL_PWMTIMER); if (!pwm) { aerr("ERROR: Failed to get the STM32 PWM lower half\n"); return -ENODEV; } /* Register the PWM driver at "/dev/pwm0" */ ret = pwm_register("/dev/pwm0", pwm); if (ret < 0) { aerr("ERROR: pwm_register failed: %d\n", ret); return ret; } /* Now we are initialized */ initialized = true; } return OK; }
int mbed_adc_setup(void) { static bool initialized = false; struct adc_dev_s *adc; int ret; /* Check if we have already initialized */ if (!initialized) { /* Call lpc17_adcinitialize() to get an instance of the ADC interface */ adc = lpc17_adcinitialize(); if (adc == NULL) { aerr("ERROR: Failed to get ADC interface\n"); return -ENODEV; } /* Register the ADC driver at "/dev/adc0" */ ret = adc_register("/dev/adc0", adc); if (ret < 0) { aerr("ERROR: adc_register failed: %d\n", ret); return ret; } /* Now we are initialized */ initialized = true; } return OK; }
FAR struct dac_dev_s *stm32_dacinitialize(int intf) { FAR struct dac_dev_s *dev; FAR struct stm32_chan_s *chan; int ret; #ifdef CONFIG_STM32_DAC1 if (intf == 1) { ainfo("DAC1-1 Selected\n"); dev = &g_dac1dev; } else if (intf == 2) { ainfo("DAC1-2 Selected\n"); dev = &g_dac2dev; } else #endif #ifdef CONFIG_STM32_DAC2 if (intf == 3) { ainfo("DAC2-1 Selected\n"); dev = &g_dac3dev; } else #endif { aerr("ERROR: No such DAC interface: %d\n", intf); errno = ENODEV; return NULL; } /* Make sure that the DAC block has been initialized */ ret = dac_blockinit(); if (ret < 0) { aerr("ERROR: Failed to initialize the DAC block: %d\n", ret); errno = -ret; return NULL; } /* Configure the selected DAC channel */ chan = dev->ad_priv; ret = dac_chaninit(chan); if (ret < 0) { aerr("ERROR: Failed to initialize DAC channel %d: %d\n", intf, ret); errno = -ret; return NULL; } return dev; }
int stm32_comp_setup(void) { static bool initialized = false; struct comp_dev_s* comp = NULL; int ret; if (!initialized) { /* Get the comparator interface */ #ifdef CONFIG_STM32_COMP2 comp = stm32_compinitialize(2); if (comp == NULL) { aerr("ERROR: Failed to get COMP%d interface\n", 2); return -ENODEV; } #endif #ifdef CONFIG_STM32_COMP4 comp = stm32_compinitialize(4); if (comp == NULL) { aerr("ERROR: Failed to get COMP%d interface\n", 4); return -ENODEV; } #endif #ifdef CONFIG_STM32_COMP6 comp = stm32_compinitialize(6); if (comp == NULL) { aerr("ERROR: Failed to get COMP%d interface\n", 6); return -ENODEV; } #endif /* Register the comparator character driver at /dev/comp0 */ ret = comp_register("/dev/comp0", comp); if (ret < 0) { aerr("ERROR: comp_register failed: %d\n", ret); return ret; } initialized = true; } return OK; }
int sam_pwm_setup(void) { static bool initialized = false; struct pwm_lowerhalf_s *pwm; int ret; /* Have we already initialized? */ if (!initialized) { /* Call sam_pwminitialize() to get an instance of the PWM interface */ pwm = sam_pwminitialize(CONFIG_SAMA5D4EK_CHANNEL); if (!pwm) { _err("ERROR: Failed to get the SAMA5 PWM lower half\n"); return -ENODEV; } /* Register the PWM driver at "/dev/pwm0" */ ret = pwm_register("/dev/pwm0", pwm); if (ret < 0) { aerr("ERROR: pwm_register failed: %d\n", ret); return ret; } /* Now we are initialized */ initialized = true; } return OK; }
static void tiva_adc_interrupt(struct tiva_adc_sse_s *sse) { int ret; int irq = tiva_adc_getirq(sse->adc, sse->num); DEBUGASSERT(sse->ena == true); /* Disable further interrupts. Interrupts will be re-enabled * after the worker thread executes. */ up_disable_irq(irq); /* Clear interrupt status */ tiva_adc_sse_clear_int(sse->adc, sse->num); /* Transfer processing to the worker thread. Since interrupts are * disabled while the work is pending, no special action should be * required to protected the work queue. */ DEBUGASSERT(sse->work.worker == NULL); ret = work_queue(HPWORK, &sse->work, tiva_adc_read, sse, 0); if (ret != 0) { aerr("ERROR: Failed to queue work: %d ADC.SSE: %d.%d\n", ret, sse->adc, sse->num); } }
static void tiva_adc_read(void *arg) { struct tiva_adc_s *priv; struct tiva_adc_sse_s *sse = (struct tiva_adc_sse_s *)arg; struct adc_dev_s *dev = 0; int irq = tiva_adc_getirq(sse->adc, sse->num); uint8_t i = 0; uint8_t fifo_count = 0; int32_t buf[8]; /* Get exclusive access to the driver data structure */ tiva_adc_lock(g_adcs[sse->adc], sse->num); /* Get sampled data */ fifo_count = tiva_adc_sse_data(sse->adc, sse->num, buf); /* Determine which adc_dev_s we need */ dev = g_devs[sse->adc]; if (dev == NULL) { /* This is a serious error: indicates invalid pointer indirection * and should cause a full system stop. */ aerr("ERROR: Invalid ADC device number given %d\n", sse->adc); DEBUGPANIC(); return; } priv = (struct tiva_adc_s *)dev->ad_priv; /* Verify that the upper-half driver has bound its callback functions */ if (priv->cb != NULL) { DEBUGASSERT(priv->cb->au_receive != NULL); for (i = 0; i < fifo_count; ++i) { /* Perform the data received callback */ priv->cb->au_receive(dev, tiva_adc_get_ain(sse->adc, sse->num, i), buf[i]); ainfo("AIN%d = 0x%04x\n", tiva_adc_get_ain(sse->adc, sse->num, i), buf[i]); } } /* Exit, re-enabling ADC interrupts */ up_enable_irq(irq); /* Release our lock on the ADC structure */ tiva_adc_unlock(g_adcs[sse->adc], sse->num); }
static int dac_ioctl(FAR struct dac_dev_s *dev, int cmd, unsigned long arg) { FAR struct stm32_chan_s *chan = dev->ad_priv; int ret = OK; switch (cmd) { #ifdef HAVE_DMA case IO_DMABUFFER_INIT: { uint16_t *buffer = (uint16_t *)arg; /* The caller is responsible for providing buffer with * suitable length equal to CONFIG_STM32_DACxCHy_DMA_BUFFER_SIZE */ dma_bufferinit(chan, buffer, chan->buffer_len * sizeof(buffer)); break; } #endif default: { aerr("ERROR: Unknown cmd: %d\n", cmd); ret = -ENOTTY; break; } } return ret; }
void Matrix3f::fixError() { Vector3f a(data, 0); Vector3f b(data, 3); float err = a.dot(b) / 2; Vector3f aerr(a.data, 0); aerr.multiply(err); Vector3f berr(a.data, 0); berr.multiply(err); a.substract(&berr); a.normalize(); b.substract(&berr); b.normalize(); Vector3f c(0, 0, 0); a.cross(b.data, c.data); for (int j = 0; j < 3; j++) { data[j] = a.data[j]; } for (int j = 0; j < 3; j++) { data[j + 3] = b.data[j]; } for (int j = 0; j < 3; j++) { data[j + 6] = c.data[j]; } }
int stm32_adc_setup(void) { #ifdef CONFIG_STM32_ADC1 static bool initialized = false; struct adc_dev_s *adc; int ret; int i; /* Check if we have already initialized */ if (!initialized) { /* Configure the pins as analog inputs for the selected channels */ for (i = 0; i < ADC1_NCHANNELS; i++) { stm32_configgpio(g_pinlist[i]); } /* Call stm32_adcinitialize() to get an instance of the ADC interface */ adc = stm32_adcinitialize(1, g_chanlist, ADC1_NCHANNELS); if (adc == NULL) { aerr("ERROR: Failed to get ADC interface\n"); return -ENODEV; } /* Register the ADC driver at "/dev/adc0" */ ret = adc_register("/dev/adc0", adc); if (ret < 0) { aerr("ERROR: adc_register failed: %d\n", ret); return ret; } /* Now we are initialized */ initialized = true; } return OK; #else return -ENOSYS; #endif }
int board_adc_setup(void) { #ifdef CONFIG_SAMA5_ADC static bool initialized = false; struct adc_dev_s *adc; int ret; /* Check if we have already initialized */ if (!initialized) { /* Call stm32_adcinitialize() to get an instance of the ADC interface */ adc = sam_adc_initialize(); if (adc == NULL) { aerr("ERROR: Failed to get ADC interface\n"); return -ENODEV; } /* Register the ADC driver at "/dev/adc0" */ ret = adc_register("/dev/adc0", adc); if (ret < 0) { aerr("ERROR: adc_register failed: %d\n", ret); return ret; } /* Now we are initialized */ initialized = true; } return OK; #else return -ENOSYS; #endif }
void tiva_adc_irq_detach(uint8_t adc, uint8_t sse) { uint32_t ret = 0; int irq = sse2irq[SSE_IDX(adc, sse)]; /* Disable ADC interrupts at the level of the AIC */ up_disable_irq(irq); /* Then detach the ADC interrupt handler. */ ret = irq_detach(irq); if (ret < 0) { aerr("ERROR: Failed to detach IRQ %d: %d\n", irq, ret); return; } }
void tiva_adc_irq_attach(uint8_t adc, uint8_t sse, xcpt_t isr) { uint32_t ret = 0; int irq = sse2irq[SSE_IDX(adc, sse)]; #ifdef CONFIG_DEBUG_ANALOG ainfo("assigning ISR=0x%p to ADC%d SSE%d IRQ=0x%02x...\n", isr, adc, sse, irq); #endif ret = irq_attach(irq, isr, NULL); if (ret < 0) { aerr("ERROR: Failed to attach IRQ %d: %d\n", irq, ret); return; } up_enable_irq(irq); }
static char *escape_string(char *s) { char buf[256]; char *t = buf; for (; *s != 0; s++) { if (*s == '"') { strcpy(t, "\\\""); t += strlen(t); continue; } if (*s == '\\') { strcpy(t, "\\\\"); t += strlen(t); continue; } *t++ = *s; } *t++ = *s; if (t - buf > sizeof(buf)) aerr("string is too long\n"); return strcpy(s, buf); }
/* * 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); } }
int i2schar_devinit(void) { static bool initialized = false; struct i2s_dev_s *i2s; int ret; /* Have we already initialized? */ if (!initialized) { /* Call sam_ssc_initialize() to get an instance of the SSC/I2S interface */ i2s = sam_ssc_initialize(CONFIG_SAMA5D3XPLAINED_SSC_PORT); if (!i2s) { _err("ERROR: Failed to get the SAMA5 SSC/I2S driver for SSC%d\n", CONFIG_SAMA5D3XPLAINED_SSC_PORT); return -ENODEV; } /* Register the I2S character driver at "/dev/i2schar0" */ ret = i2schar_register(i2s, CONFIG_SAMA5D3XPLAINED_I2SCHAR_MINOR); if (ret < 0) { aerr("ERROR: i2schar_register failed: %d\n", ret); return ret; } /* Now we are initialized */ initialized = true; } return OK; }
int mbed_pwm_setup(void) { static bool initialized = false; struct pwm_lowerhalf_s *pwm; struct pwm_lowerhalf_s *mcpwm; struct pwm_lowerhalf_s *timer; int ret; /* Have we already initialized? */ if (!initialized) { /* Call lpc17_pwminitialize() to get an instance of the PWM interface */ pwm = lpc17_pwminitialize(0); if (!pwm) { aerr("ERROR: Failed to get the LPC17XX PWM lower half\n"); return -ENODEV; } /* Register the PWM driver at "/dev/pwm0" */ ret = pwm_register("/dev/pwm0", pwm); if (ret < 0) { aerr("ERROR: pwm_register failed: %d\n", ret); return ret; } mcpwm = lpc17_mcpwminitialize(0); if (!mcpwm) { aerr("ERROR: Failed to get the LPC17XX MOTOR PWM lower half\n"); return -ENODEV; } /* Register the MOTOR CONTROL PWM driver at "/dev/mcpwm0" */ ret = pwm_register("/dev/mcpwm0", mcpwm); if (ret < 0) { aerr("ERROR: mcpwm_register failed: %d\n", ret); return ret; } timer = lpc17_timerinitialize(0); if (!timer) { aerr("ERROR: Failed to get the LPC17XX TIMER lower half\n"); return -ENODEV; } /* Register the PWM driver at "/dev/timer0" */ ret = pwm_register("/dev/timer0", timer); if (ret < 0) { aerr("ERROR: timer_register failed: %d\n", ret); return ret; } /* Now we are initialized */ initialized = true; } return OK; }
static int dac_chaninit(FAR struct stm32_chan_s *chan) { uint16_t clearbits; uint16_t setbits; #ifdef HAVE_TIMER int ret; #endif /* Is the selected channel already in-use? */ if (chan->inuse) { /* Yes.. then return EBUSY */ return -EBUSY; } /* Configure the DAC output pin: * * DAC -" Once the DAC channelx is enabled, the corresponding GPIO pin * (PA4 or PA5) is automatically connected to the analog converter output * (DAC_OUTx). In order to avoid parasitic consumption, the PA4 or PA5 pin * should first be configured to analog (AIN)". */ stm32_configgpio(chan->pin); /* DAC channel configuration: * * - Set the trigger selection based upon the configuration. * - Set wave generation == None. * - Enable the output buffer. */ /* Disable before change */ stm32_dac_modify_cr(chan, DAC_CR_EN, 0); clearbits = DAC_CR_TSEL_MASK | DAC_CR_MAMP_MASK | DAC_CR_WAVE_MASK | DAC_CR_BOFF; setbits = chan->tsel | /* Set trigger source (SW or timer TRGO event) */ DAC_CR_MAMP_AMP1 | /* Set waveform characteristics */ DAC_CR_WAVE_DISABLED | /* Set no noise */ DAC_CR_BOFF_EN; /* Enable output buffer */ stm32_dac_modify_cr(chan, clearbits, setbits); #ifdef HAVE_DMA /* Determine if DMA is supported by this channel */ if (chan->hasdma) { /* Remap DMA request if necessary*/ dma_remap(chan); /* DAC trigger enable if not external triggering */ if (!chan->text) { stm32_dac_modify_cr(chan, 0, DAC_CR_TEN); } /* Allocate a DMA channel */ chan->dma = stm32_dmachannel(chan->dmachan); if (!chan->dma) { aerr("ERROR: Failed to allocate a DMA channel\n"); return -EBUSY; } /* Configure the timer that supports the DMA operation * Do nothing if HRTIM is selected as trigger. * All necessary configuration is done in the HRTIM driver. */ #ifdef HAVE_TIMER if (chan->timer != TIM_INDEX_HRTIM) { ret = dac_timinit(chan); if (ret < 0) { aerr("ERROR: Failed to initialize the DMA timer: %d\n", ret); return ret; } } #endif } #endif /* Mark the DAC channel "in-use" */ chan->inuse = 1; return OK; }
static int dac_timinit(FAR struct stm32_chan_s *chan) { uint32_t pclk; uint32_t prescaler; uint32_t timclk; uint32_t reload; uint32_t regaddr; uint32_t setbits; /* Configure the time base: Timer period, prescaler, clock division, * counter mode (up). */ /* Enable the timer. At most, two of the following cases (pluse the * default) will be enabled */ regaddr = STM32_RCC_APB1ENR; switch (chan->timer) { #ifdef NEED_TIM2 case 2: setbits = RCC_APB1ENR_TIM2EN; pclk = BOARD_TIM2_FREQUENCY; break; #endif #ifdef NEED_TIM3 case 3: setbits = RCC_APB1ENR_TIM3EN; pclk = BOARD_TIM3_FREQUENCY; break; #endif #ifdef NEED_TIM4 case 4: setbits = RCC_APB1ENR_TIM4EN; pclk = BOARD_TIM4_FREQUENCY; break; #endif #ifdef NEED_TIM5 case 5: setbits = RCC_APB1ENR_TIM5EN; pclk = BOARD_TIM5_FREQUENCY; break; #endif #ifdef NEED_TIM6 case 6: setbits = RCC_APB1ENR_TIM6EN; pclk = BOARD_TIM6_FREQUENCY; break; #endif #ifdef NEED_TIM7 case 7: setbits = RCC_APB1ENR_TIM7EN; pclk = BOARD_TIM7_FREQUENCY; break; #endif #ifdef NEED_TIM8 case 8: regaddr = STM32_RCC_APB2ENR; setbits = RCC_APB2ENR_TIM8EN; pclk = BOARD_TIM8_FREQUENCY; break; #endif default: aerr("ERROR: Could not enable timer\n"); return -EINVAL; } /* Enable the timer. */ modifyreg32(regaddr, 0, setbits); /* Calculate optimal values for the timer prescaler and for the timer reload * register. If 'frequency' is the desired frequency, then * * reload = timclk / frequency * timclk = pclk / presc * * Or, * * reload = pclk / presc / frequency * * There are many solutions to this this, but the best solution will be the * one that has the largest reload value and the smallest prescaler value. * That is the solution that should give us the most accuracy in the timer * control. Subject to: * * 0 <= presc <= 65536 * 1 <= reload <= 65535 * * So presc = pclk / 65535 / frequency would be optimal. * * Example: * * pclk = 42 MHz * frequency = 100 Hz * * prescaler = 42,000,000 / 65,535 / 100 * = 6.4 (or 7 -- taking the ceiling always) * timclk = 42,000,000 / 7 * = 6,000,000 * reload = 6,000,000 / 100 * = 60,000 */ prescaler = (pclk / chan->tfrequency + 65534) / 65535; if (prescaler < 1) { prescaler = 1; } else if (prescaler > 65536) { prescaler = 65536; } timclk = pclk / prescaler; reload = timclk / chan->tfrequency; if (reload < 1) { reload = 1; } else if (reload > 65535) { reload = 65535; } /* Set the reload and prescaler values */ tim_putreg(chan, STM32_BTIM_ARR_OFFSET, (uint16_t)reload); tim_putreg(chan, STM32_BTIM_PSC_OFFSET, (uint16_t)(prescaler - 1)); /* Count mode up, auto reload */ tim_modifyreg(chan, STM32_BTIM_CR1_OFFSET, 0, ATIM_CR1_ARPE); /* Selection TRGO selection: update */ tim_modifyreg(chan, STM32_BTIM_CR2_OFFSET, ATIM_CR2_MMS_MASK, ATIM_CR2_MMS_UPDATE); /* Update DMA request enable ???? */ #if 0 tim_modifyreg(chan, STM32_BTIM_DIER_OFFSET, 0, ATIM_DIER_UDE); #endif /* Enable the counter */ tim_modifyreg(chan, STM32_BTIM_CR1_OFFSET, 0, ATIM_CR1_CEN); return OK; }
/* Classify argument as to address mode */ int addr(struct expr *esp) { int c; unsigned 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; 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); }
int stm32_adc_setup(void) { static bool initialized = false; FAR struct adc_dev_s *adc; int ret; int i; /* Check if we have already initialized */ if (!initialized) { /* DEV1 */ /* Configure the pins as analog inputs for the selected channels */ for (i = 0; i < DEV1_NCHANNELS; i++) { stm32_configgpio(g_pinlist1[i]); } /* Call stm32_adcinitialize() to get an instance of the ADC interface */ adc = stm32_adcinitialize(DEV1_PORT, g_chanlist1, DEV1_NCHANNELS); if (adc == NULL) { aerr("ERROR: Failed to get ADC interface 1\n"); return -ENODEV; } /* Register the ADC driver at "/dev/adc0" */ ret = adc_register("/dev/adc0", adc); if (ret < 0) { aerr("ERROR: adc_register /dev/adc0 failed: %d\n", ret); return ret; } #ifdef DEV2_PORT /* DEV2 */ /* Configure the pins as analog inputs for the selected channels */ for (i = 0; i < DEV2_NCHANNELS; i++) { stm32_configgpio(g_pinlist2[i]); } /* Call stm32_adcinitialize() to get an instance of the ADC interface */ adc = stm32_adcinitialize(DEV2_PORT, g_chanlist2, DEV2_NCHANNELS); if (adc == NULL) { aerr("ERROR: Failed to get ADC interface 2\n"); return -ENODEV; } /* Register the ADC driver at "/dev/adc1" */ ret = adc_register("/dev/adc1", adc); if (ret < 0) { aerr("ERROR: adc_register /dev/adc1 failed: %d\n", ret); return ret; } #endif initialized = true; } return OK; }
int tiva_adc_initialize(const char *devpath, struct tiva_adc_cfg_s *cfg, uint32_t clock, uint8_t sample_rate) { struct tiva_adc_s *adc; int ret = 0; ainfo("initializing...\n"); /* Initialize the private ADC device data structure */ adc = tiva_adc_struct_init(cfg); if (adc == NULL) { aerr("ERROR: Invalid ADC device number: expected=%d actual=%d\n", 0, cfg->adc); return -ENODEV; } /* Turn on peripheral */ if (tiva_adc_enable(adc->devno, true) < 0) { aerr("ERROR: failure to power ADC peripheral (devno=%d)\n", cfg->adc); return ret; } /* Perform actual initialization */ tiva_adc_one_time_init(clock, sample_rate); tiva_adc_configure(cfg); tiva_adc_irqinitialize(cfg); /* Now we are initialized */ adc->ena = true; adc->cb = NULL; #ifdef CONFIG_DEBUG_ANALOG tiva_adc_runtimeobj_vals(); #endif /* Ensure our lower half is valid */ if (adc->dev == NULL) { aerr("ERROR: Failed to get interface %s\n", devpath); return -ENODEV; } ainfo("adc_dev_s=0x%08x\n", adc->dev); /* Register the ADC driver */ ainfo("Register the ADC driver at %s\n", devpath); ret = adc_register(devpath, adc->dev); if (ret < 0) { aerr("ERROR: Failed to register %s to character driver: %d\n", devpath, ret); return ret; } return OK; }
int main(int argc, char *argv[]) { FILE *fout, *fasm, *fhdr = NULL, *frlist; const struct parsed_proto *pp; int no_decorations = 0; char comment_char = '#'; char words[20][256]; char word[256]; char line[256]; char last_sym[32]; unsigned long val; unsigned long cnt; const char *sym; enum dx_type type; char **pub_syms; int pub_sym_cnt = 0; int pub_sym_alloc; char **rlist; int rlist_cnt = 0; int rlist_alloc; int header_mode = 0; int is_ro = 0; int is_label; int is_bss; int wordc; int first; int arg_out; int arg = 1; int len; int w, i; char *p; char *p2; if (argc < 4) { // -nd: no symbol decorations printf("usage:\n%s [-nd] [-i] [-a] <.s> <.asm> <hdrf> [rlist]*\n" "%s -hdr <.h> <.asm>\n", argv[0], argv[0]); return 1; } for (arg = 1; arg < argc; arg++) { if (IS(argv[arg], "-nd")) no_decorations = 1; else if (IS(argv[arg], "-i")) g_cconv_novalidate = 1; else if (IS(argv[arg], "-a")) { comment_char = '@'; g_arm_mode = 1; } else if (IS(argv[arg], "-hdr")) header_mode = 1; else break; } arg_out = arg++; asmfn = argv[arg++]; fasm = fopen(asmfn, "r"); my_assert_not(fasm, NULL); if (!header_mode) { hdrfn = argv[arg++]; fhdr = fopen(hdrfn, "r"); my_assert_not(fhdr, NULL); } fout = fopen(argv[arg_out], "w"); my_assert_not(fout, NULL); pub_sym_alloc = 64; pub_syms = malloc(pub_sym_alloc * sizeof(pub_syms[0])); my_assert_not(pub_syms, NULL); rlist_alloc = 64; rlist = malloc(rlist_alloc * sizeof(rlist[0])); my_assert_not(rlist, NULL); for (; arg < argc; arg++) { frlist = fopen(argv[arg], "r"); my_assert_not(frlist, NULL); while (my_fgets(line, sizeof(line), frlist)) { p = sskip(line); if (*p == 0 || *p == ';') continue; p = next_word(words[0], sizeof(words[0]), p); if (words[0][0] == 0) continue; if (rlist_cnt >= rlist_alloc) { rlist_alloc = rlist_alloc * 2 + 64; rlist = realloc(rlist, rlist_alloc * sizeof(rlist[0])); my_assert_not(rlist, NULL); } rlist[rlist_cnt++] = strdup(words[0]); } fclose(frlist); frlist = NULL; } if (rlist_cnt > 0) qsort(rlist, rlist_cnt, sizeof(rlist[0]), cmpstringp); qsort(unwanted_syms, ARRAY_SIZE(unwanted_syms), sizeof(unwanted_syms[0]), cmpstringp); last_sym[0] = 0; while (1) { next_section(fasm, line); if (feof(fasm)) break; if (IS(line + 1, "text")) continue; if (IS(line + 1, "rdata")) { is_ro = 1; if (!header_mode) fprintf(fout, "\n.section .rodata\n"); } else if (IS(line + 1, "data")) { is_ro = 0; if (!header_mode) fprintf(fout, "\n.data\n"); } else aerr("unhandled section: '%s'\n", line); if (!header_mode) fprintf(fout, ".align %d\n", align_value(4)); while (my_fgets(line, sizeof(line), fasm)) { sym = NULL; asmln++; p = sskip(line); if (*p == 0) continue; if (*p == ';') { if (IS_START(p, ";org") && sscanf(p + 5, "%Xh", &i) == 1) { // ;org is only seen at section start, so assume . addr 0 i &= 0xfff; if (i != 0 && !header_mode) fprintf(fout, "\t\t .skip 0x%x\n", i); } continue; } for (wordc = 0; wordc < ARRAY_SIZE(words); wordc++) { p = sskip(next_word_s(words[wordc], sizeof(words[0]), p)); if (*p == 0 || *p == ';') { wordc++; break; } if (*p == ',') { p = sskip(p + 1); } } if (*p == ';') { p = sskip(p + 1); if (IS_START(p, "sctclrtype")) g_func_sym_pp = NULL; } if (wordc == 2 && IS(words[1], "ends")) break; if (wordc <= 2 && IS(words[0], "end")) break; if (wordc < 2) aerr("unhandled: '%s'\n", words[0]); // don't cares if (IS(words[0], "assume")) continue; if (IS(words[0], "align")) { if (header_mode) continue; val = parse_number(words[1]); fprintf(fout, "\t\t .align %d", align_value(val)); goto fin; } w = 1; type = parse_dx_directive(words[0]); if (type == DXT_UNSPEC) { type = parse_dx_directive(words[1]); sym = words[0]; w = 2; } if (type == DXT_UNSPEC) aerr("unhandled decl: '%s %s'\n", words[0], words[1]); if (sym != NULL) { if (header_mode) { int is_str = 0; fprintf(fout, "extern "); if (is_ro) fprintf(fout, "const "); switch (type) { case DXT_BYTE: for (i = w; i < wordc; i++) if (words[i][0] == '\'') is_str = 1; if (is_str) fprintf(fout, "char %s[];\n", sym); else fprintf(fout, "uint8_t %s;\n", sym); break; case DXT_WORD: fprintf(fout, "uint16_t %s;\n", sym); break; case DXT_DWORD: fprintf(fout, "uint32_t %s;\n", sym); break; default: fprintf(fout, "_UNKNOWN %s;\n", sym); break; } continue; } snprintf(last_sym, sizeof(last_sym), "%s", sym); pp = proto_parse(fhdr, sym, 1); if (pp != NULL) { g_func_sym_pp = NULL; // public/global name if (pub_sym_cnt >= pub_sym_alloc) { pub_sym_alloc *= 2; pub_syms = realloc(pub_syms, pub_sym_alloc * sizeof(pub_syms[0])); my_assert_not(pub_syms, NULL); } pub_syms[pub_sym_cnt++] = strdup(sym); } len = strlen(sym); fprintf(fout, "%s%s:", no_decorations ? "" : "_", sym); len += 2; if (len < 8) fprintf(fout, "\t"); if (len < 16) fprintf(fout, "\t"); if (len <= 16) fprintf(fout, " "); else fprintf(fout, " "); } else { if (header_mode) continue; fprintf(fout, "\t\t "); } // fill out some unwanted strings with zeroes.. if (type == DXT_BYTE && words[w][0] == '\'' && is_unwanted_sym(last_sym)) { len = 0; for (; w < wordc; w++) { if (words[w][0] == '\'') { p = words[w] + 1; for (; *p && *p != '\''; p++) len++; } else { // assume encoded byte len++; } } fprintf(fout, ".skip %d", len); goto fin; } else if (type == DXT_BYTE && (words[w][0] == '\'' || (w + 1 < wordc && words[w + 1][0] == '\''))) { // string; use asciz for most common case if (w == wordc - 2 && IS(words[w + 1], "0")) { fprintf(fout, ".asciz \""); wordc--; } else fprintf(fout, ".ascii \""); for (; w < wordc; w++) { if (words[w][0] == '\'') { p = words[w] + 1; p2 = strchr(p, '\''); if (p2 == NULL) aerr("unterminated string? '%s'\n", p); memcpy(word, p, p2 - p); word[p2 - p] = 0; fprintf(fout, "%s", escape_string(word)); } else { val = parse_number(words[w]); if (val & ~0xff) aerr("bad string trailing byte?\n"); // unfortunately \xHH is unusable - gas interprets // things like \x27b as 0x7b, so have to use octal here fprintf(fout, "\\%03lo", val); } } fprintf(fout, "\""); goto fin; } if (w == wordc - 2) { if (IS_START(words[w + 1], "dup(")) { cnt = parse_number(words[w]); p = words[w + 1] + 4; p2 = strchr(p, ')'); if (p2 == NULL) aerr("bad dup?\n"); memmove(word, p, p2 - p); word[p2 - p] = 0; val = 0; if (!IS(word, "?")) val = parse_number(word); fprintf(fout, ".fill 0x%02lx,%d,0x%02lx", cnt, type_size(type), val); goto fin; } } if (type == DXT_DWORD && words[w][0] == '\'' && words[w][5] == '\'' && strlen(words[w]) == 6) { if (w != wordc - 1) aerr("TODO\n"); p = words[w]; val = (p[1] << 24) | (p[2] << 16) | (p[3] << 8) | p[4]; fprintf(fout, ".long 0x%lx", val); snprintf(g_comment, sizeof(g_comment), "%s", words[w]); goto fin; } if (type >= DXT_DWORD && strchr(words[w], '.')) { if (w != wordc - 1) aerr("TODO\n"); if (g_arm_mode && type == DXT_TEN) { fprintf(fout, ".fill 10"); snprintf(g_comment, sizeof(g_comment), "%s %s", type_name_float(type), words[w]); } else fprintf(fout, "%s %s", type_name_float(type), words[w]); goto fin; } first = 1; fprintf(fout, "%s ", type_name(type)); for (; w < wordc; w++) { if (!first) fprintf(fout, ", "); is_label = is_bss = 0; if (w <= wordc - 2 && IS(words[w], "offset")) { is_label = 1; w++; } else if (IS(words[w], "?")) { is_bss = 1; } else if (type == DXT_DWORD && !('0' <= words[w][0] && words[w][0] <= '9')) { // assume label is_label = 1; } if (is_bss) { fprintf(fout, "0"); } else if (is_label) { p = words[w]; if (IS_START(p, "loc_") || IS_START(p, "__imp") || strchr(p, '?') || strchr(p, '@') || bsearch(&p, rlist, rlist_cnt, sizeof(rlist[0]), cmpstringp)) { fprintf(fout, "0"); snprintf(g_comment, sizeof(g_comment), "%s", p); } else { pp = check_var(fhdr, sym, p); if (pp == NULL) { fprintf(fout, "%s%s", (no_decorations || p[0] == '_') ? "" : "_", p); } else { if (no_decorations) fprintf(fout, "%s", pp->name); else output_decorated_pp(fout, pp); } } } else { val = parse_number(words[w]); if (val < 10) fprintf(fout, "%ld", val); else fprintf(fout, "0x%lx", val); } first = 0; } fin: if (g_comment[0] != 0) { fprintf(fout, "\t\t%c %s", comment_char, g_comment); g_comment[0] = 0; } fprintf(fout, "\n"); } } fprintf(fout, "\n"); // dump public syms for (i = 0; i < pub_sym_cnt; i++) fprintf(fout, ".global %s%s\n", no_decorations ? "" : "_", pub_syms[i]); fclose(fout); fclose(fasm); if (fhdr != NULL) fclose(fhdr); return 0; }
static const struct parsed_proto *check_var(FILE *fhdr, const char *sym, const char *varname) { const struct parsed_proto *pp, *pp_sym; char fp_sym[256], fp_var[256], *p; int i; pp = proto_parse(fhdr, varname, 1); if (pp == NULL) { if (IS_START(varname, "sub_")) awarn("sub_ sym missing proto: '%s'\n", varname); return NULL; } if (!pp->is_func && !pp->is_fptr) return NULL; pp_print(fp_var, sizeof(fp_var), pp); if (pp->argc_reg == 0) goto check_sym; if (pp->argc_reg == 1 && pp->argc_stack == 0 && IS(pp->arg[0].reg, "ecx")) { goto check_sym; } if (!g_cconv_novalidate && (pp->argc_reg != 2 || !IS(pp->arg[0].reg, "ecx") || !IS(pp->arg[1].reg, "edx"))) { awarn("unhandled reg call: %s\n", fp_var); } check_sym: // fptrs must use 32bit args, callsite might have no information and // lack a cast to smaller types, which results in incorrectly masked // args passed (callee may assume masked args, it does on ARM) for (i = 0; i < pp->argc; i++) { if (pp->arg[i].type.is_ptr) continue; p = pp->arg[i].type.name; if (strstr(p, "int8") || strstr(p, "int16") || strstr(p, "char") || strstr(p, "short")) { awarn("reference to %s with arg%d '%s'\n", pp->name, i + 1, p); } } sprint_pp_short(pp, g_comment, sizeof(g_comment)); if (sym != NULL) { g_func_sym_pp = NULL; pp_sym = proto_parse(fhdr, sym, 1); if (pp_sym == NULL) return pp; if (!pp_sym->is_fptr) aerr("func ptr data, but label '%s' !is_fptr\n", pp_sym->name); g_func_sym_pp = pp_sym; } else { pp_sym = g_func_sym_pp; if (pp_sym == NULL) return pp; } if (pp_cmp_func(pp, pp_sym)) { pp_print(fp_sym, sizeof(fp_sym), pp_sym); anote("var: %s\n", fp_var); anote("sym: %s\n", fp_sym); awarn("^ mismatch\n"); } return pp; }
/* * Process machine ops. */ VOID machine(struct mne *mp) { char *p, *str; char pid[NINPUT], id[NINPUT]; int c, d, t, t1, v1; a_uint op; struct sym *sp; struct expr e, e1, e2; clrexpr(&e); clrexpr(&e1); clrexpr(&e2); op = mp->m_valu; switch (mp->m_type) { case S_CPU: opcycles = OPCY_CPU; lmode = SLIST; switch(op) { default: op = DS8XCXXX; case DS8XCXXX: v1 = 2; str = "DS8XCXXX"; sym[2].s_addr = X_DS8XCXXX; break; case DS80C310: v1 = 2; str = "DS80C310"; sym[2].s_addr = X_DS80C310; break; case DS80C320: v1 = 2; str = "DS80C320"; sym[2].s_addr = X_DS80C320; break; case DS80C323: v1 = 2; str = "DS80C323"; sym[2].s_addr = X_DS80C323; break; case DS80C390: v1 = 3; str = "DS80C390"; sym[2].s_addr = X_DS80C390; break; case DS83C520: v1 = 2; str = "DS83C520"; sym[2].s_addr = X_DS83C520; break; case DS83C530: v1 = 2; str = "DS83C530"; sym[2].s_addr = X_DS83C530; break; case DS83C550: v1 = 2; str = "DS83C550"; sym[2].s_addr = X_DS83C550; break; case DS87C520: v1 = 2; str = "DS87C520"; sym[2].s_addr = X_DS87C520; break; case DS87C530: v1 = 2; str = "DS87C530"; sym[2].s_addr = X_DS87C530; break; case DS87C550: v1 = 2; str = "DS87C550"; sym[2].s_addr = X_DS87C550; break; case DS______: v1 = 2; str = "DS______"; sym[2].s_addr = X_DS______; if (more()) { str = p = pid; d = getnb(); while ((c = get()) != d) { if (c == '\0') { qerr(); } if (p < &pid[sizeof(pid)-3]) { *p++ = c; } else { break; } } *p = 0; } break; } if (op != 0) { ds8_bytes = v1; exprmasks(v1); } mchtyp = (int) op; sprintf(id, "__%s", str); sp = lookup(id); if (sp->s_type != S_NEW && (sp->s_flag & S_ASG) == 0) { err('m'); } sp->s_type = S_USER; sp->s_addr = 1; sp->s_flag |= S_ASG; sprintf(buff, "%s %s", DS_CPU, str); cpu = buff; sp = lookup("__SFR_BITS"); if (sp->s_type != S_NEW && (sp->s_flag & S_ASG) == 0) { err('m'); } sp->s_type = S_USER; sp->s_flag |= S_ASG; if (more()) { expr(&e, 0); abscheck(&e); sp->s_addr = e.e_addr; } else { sp->s_addr = 1; } break; case S_AMODE: opcycles = OPCY_AMODE; if ((mchtyp != 0) && (mchtyp != DS80C390)) { err('o'); break; } expr(&e, 0); abscheck(&e); amode = (int) e.e_addr; if ((amode < 0) || (amode > 2)) { amode = 0; err('o'); } if ((c = getnb()) == ',') { expr(&e1, 0); abscheck(&e1); if (e1.e_addr != 0) { /* mov ta,#0aah */ outab(0x075); outab(0x0C7); outab(0x0AA); /* mov ta,#055h */ outab(0x075); outab(0x0C7); outab(0x055); /* mov acon,#amode */ outab(0x075); outab(0x09D); outab(amode); } else { lmode = SLIST; } } else { unget(c); lmode = SLIST; } break; case S_BITS: if (ds8_bytes == 0) { ds8_bytes = (int) op; exprmasks(ds8_bytes); } else if (ds8_bytes != (int) op) { err('m'); } opcycles = OPCY_BITS; lmode = SLIST; break; case S_INH: outab(op); break; case S_JMP11: expr(&e, 0); if (amode == 2) { outr3bm(&e, R_J19, op); } else { outrwm(&e, R_J11, op); } break; case S_JMP16: expr(&e, 0); outab(op); if (amode == 2) { outr3b(&e, R_NORM); } else { outrw(&e, R_NORM); } break; case S_ACC: t = addr(&e); if (t != S_A) aerr(); outab(op); break; case S_TYP1: /* A, direct, @R0, @R1, R0 to R7. "INC" also allows DPTR */ t = addr(&e); switch (t) { case S_A: outab(op + 4); break; case S_DIR: case S_EXT: /* Direct is also legal */ outab(op + 5); outrb(&e, R_PAG0); break; case S_AT_R: outab(op + 6 + e.e_addr); break; case S_REG: outab(op + 8 + e.e_addr); break; case S_DPTR: if (op != 0) /* only INC (op=0) has DPTR mode */ aerr(); else outab( 0xA3); break; default: aerr(); } break; case S_TYP2: /* A,#imm; A,direct; A,@R0; A,@R1; A,R0 to A,R7 */ t = addr(&e); if (t != S_A) aerr(); comma(1); t1 = addr(&e1); switch (t1) { case S_IMMED: outab(op + 4); outrb(&e1, R_NORM); break; case S_DIR: case S_EXT: outab(op + 5); outrb(&e1, R_PAG0); break; case S_AT_R: outab(op + 6 + e1.e_addr); break; case S_REG: outab(op + 8 + (e1.e_addr)); break; default: aerr(); } break; case S_TYP3: /* dir,A; dir,#imm; * A,#imm; A,direct; A,@R0; A,@R1; A,R0 to A,R7 * C,direct; C,/direct */ t = addr(&e); comma(1); t1 = addr(&e1); switch (t) { case S_DIR: case S_EXT: switch (t1) { case S_A: outab(op + 2); outrb(&e, R_PAG0); break; case S_IMMED: outab(op + 3); outrb(&e, R_PAG0); outrb(&e1, R_NORM); break; default: aerr(); } break; case S_A: switch (t1) { case S_IMMED: outab(op + 4); outrb(&e1, R_NORM); break; case S_DIR: case S_EXT: outab(op + 5); outrb(&e1, R_PAG0); break; case S_AT_R: outab(op + 6 + e1.e_addr); break; case S_REG: outab(op + 8 + e1.e_addr); break; default: aerr(); } break; case S_C: /* XRL has no boolean version. Trap it */ if (op == 0x60) aerr(); switch (t1) { case S_DIR: case S_EXT: outab(op + 0x32); outrb(&e1, R_PAG0); break; case S_NOT_BIT: outab(op + 0x60); outrb(&e1, R_PAG0); break; default: aerr(); } break; default: aerr(); } break; case S_TYP4: /* A,direct; A,@R0; A,@R1; A,R0 to A,R7 */ t = addr(&e); if (t != S_A) aerr(); comma(1); t1 = addr(&e1); switch (t1) { case S_DIR: case S_EXT: outab(op + 5); outrb(&e1, R_PAG0); break; case S_AT_R: outab(op + 6 + e1.e_addr); break; case S_REG: outab(op + 8 + e1.e_addr); break; default: aerr(); } break; /* MOV instruction, all modes */ case S_MOV: t = addr(&e); comma(1); t1 = addr(&e1); switch (t) { case S_A: switch (t1) { case S_IMMED: outab(0x74); outrb(&e1, R_NORM); break; case S_DIR: case S_EXT: outab(0xE5); outrb(&e1, R_PAG0); break; case S_AT_R: outab(0xE6 + e1.e_addr); break; case S_REG: outab(0xE8 + e1.e_addr); break; default: aerr(); } break; case S_REG: switch (t1) { case S_A: outab(0xF8 + e.e_addr); break; case S_IMMED: outab(0x78 + e.e_addr); outrb(&e1, R_NORM); break; case S_DIR: case S_EXT: outab(0xA8 + e.e_addr); outrb(&e1, R_PAG0); break; default: aerr(); } break; case S_DIR: case S_EXT: switch (t1) { case S_A: outab(0xF5); outrb(&e, R_PAG0); break; case S_IMMED: outab(0x75); outrb(&e, R_PAG0); outrb(&e1, R_NORM); break; case S_DIR: case S_EXT: outab(0x85); outrb(&e1, R_PAG0); outrb(&e, R_PAG0); break; case S_AT_R: outab(0x86 + e1.e_addr); outrb(&e, R_PAG0); break; case S_REG: outab(0x88 + e1.e_addr); outrb(&e, R_PAG0); break; case S_C: outab(0x92); outrb(&e, R_PAG0); break; default: aerr(); } break; case S_AT_R: switch (t1) { case S_IMMED: outab(0x76 + e.e_addr); outrb(&e1, R_NORM); break; case S_DIR: case S_EXT: outab(0xA6 + e.e_addr); outrb(&e1, R_PAG0); break; case S_A: outab(0xF6 + e.e_addr); break; default: aerr(); } break; case S_C: if ((t1 != S_DIR) && (t1 != S_EXT)) aerr(); outab(0xA2); outrb(&e1, R_PAG0); break; case S_DPTR: if (t1 != S_IMMED) aerr(); outab(0x90); if (amode == 2) outr3b(&e1, R_NORM); else outrw(&e1, R_NORM); break; default: aerr(); } break; case S_BITBR: /* JB, JBC, JNB bit,rel */ /* Branch on bit set/clear */ t = addr(&e); if ((t != S_DIR) && (t != S_EXT)) aerr(); /* sdcc svn rev #4994: fixed bug 1865114 */ comma(1); expr(&e1, 0); outab(op); outrb(&e, R_PAG0); if (mchpcr(&e1)) { v1 = (int) (e1.e_addr - dot.s_addr - 1); /* sdcc svn rev #602: Fix some path problems */ if (pass == 2 && ((v1 < -128) || (v1 > 127))) aerr(); outab(v1); } else { outrb(&e1, R_PCR); } if (e1.e_mode != S_USER) rerr(); break; case S_BR: /* JC, JNC, JZ, JNZ */ /* Relative branch */ /* sdcc svn rev #4994: fixed bug 1865114 */ expr(&e1, 0); outab(op); if (mchpcr(&e1)) { v1 = (int) (e1.e_addr - dot.s_addr - 1); /* sdcc svn rev #602: Fix some path problems */ if (pass == 2 && ((v1 < -128) || (v1 > 127))) aerr(); outab(v1); } else { outrb(&e1, R_PCR); } if (e1.e_mode != S_USER) rerr(); break; case S_CJNE: /* A,#; A,dir; @R0,#; @R1,#; Rn,# */ t = addr(&e); comma(1); t1 = addr(&e1); /* Benny */ comma(1); expr(&e2, 0); switch (t) { case S_A: if (t1 == S_IMMED) { outab(op + 4); outrb(&e1, R_NORM); } else if ((t1 == S_DIR) || (t1 == S_EXT)) { outab(op + 5); outrb(&e1, R_PAG0); } else aerr(); break; case S_AT_R: outab(op + 6 + e.e_addr); if (t1 != S_IMMED) aerr(); outrb(&e1, R_NORM); break; case S_REG: outab(op + 8 + e.e_addr); if (t1 != S_IMMED) aerr(); outrb(&e1, R_NORM); break; default: aerr(); break; } /* branch destination */ if (mchpcr(&e2)) { v1 = (int) (e2.e_addr - dot.s_addr - 1); /* sdcc svn rev #602: Fix some path problems */ if (pass == 2 && ((v1 < -128) || (v1 > 127))) aerr(); outab(v1); } else { outrb(&e2, R_PCR); } if (e2.e_mode != S_USER) rerr(); break; case S_DJNZ: /* Dir,dest; Reg,dest */ t = addr(&e); /* sdcc svn rev #4994: fixed bug 1865114 */ comma(1); expr(&e1, 0); switch (t) { case S_DIR: case S_EXT: outab(op + 5); outrb(&e, R_PAG0); break; case S_REG: outab(op + 8 + e.e_addr); break; default: aerr(); } /* branch destination */ /* sdcc svn rev #4994: fixed bug 1865114 */ if (mchpcr(&e1)) { v1 = (int) (e1.e_addr - dot.s_addr - 1); /* sdcc svn rev #602: Fix some path problems */ if (pass == 2 && ((v1 < -128) || (v1 > 127))) aerr(); outab(v1); } else { outrb(&e1, R_PCR); } if (e1.e_mode != S_USER) rerr(); break; case S_JMP: /* @A+DPTR */ t = addr(&e); if (t != S_AT_ADP) aerr(); outab(op); break; case S_MOVC: /* A,@A+DPTR A,@A+PC */ t = addr(&e); if (t != S_A) aerr(); comma(1); t1 = addr(&e1); if (t1 == S_AT_ADP) outab(0x93); else if (t1 == S_AT_APC) outab(0x83); else aerr(); break; case S_MOVX: /* A,@DPTR A,@R0 A,@R1 @DPTR,A @R0,A @R1,A */ t = addr(&e); comma(1); t1 = addr(&e1); switch (t) { case S_A: switch (t1) { case S_AT_DP: outab(0xE0); break; case S_AT_R: outab(0xE2 + e1.e_addr); break; default: aerr(); } break; case S_AT_DP: if (t1 == S_A) outab(0xF0); else aerr(); break; case S_AT_R: if (t1 == S_A) outab(0xF2 + e.e_addr); else aerr(); break; default: aerr(); } break; /* MUL/DIV A,B */ case S_AB: t = addr(&e); if (t != S_RAB) aerr(); outab(op); break; /* CLR or CPL: A, C, or bit */ case S_ACBIT: t = addr(&e); switch (t) { case S_A: if (op == 0xB2) outab(0xF4); else outab(0xE4); break; case S_C: outab(op+1); break; case S_DIR: case S_EXT: outab(op); outrb(&e, R_PAG0); break; default: aerr(); } break; /* SETB C or bit */ case S_SETB: t = addr(&e); switch (t) { case S_C: outab(op+1); break; case S_DIR: case S_EXT: outab(op); outrb(&e, R_PAG0); break; default: aerr(); } break; /* direct */ case S_DIRECT: t = addr(&e); if (t == S_A) { e.e_addr = 0xE0; e.e_mode = S_DIR; } else if ((t != S_DIR) && (t != S_EXT)) { aerr(); break; } outab(op); outrb(&e, R_PAG0); break; /* XCHD A,@Rn */ case S_XCHD: t = addr(&e); if (t != S_A) aerr(); comma(1); t1 = addr(&e1); switch (t1) { case S_AT_R: outab(op + e1.e_addr); break; default: aerr(); } break; default: opcycles = OPCY_ERR; err('o'); break; } if (opcycles == OPCY_NONE) { opcycles = ds8pg1[cb[0] & 0xFF]; } }
/* * Process a machine op. */ VOID machine(struct mne * mp) { int op, t1, t2; struct expr e1, e2; int rf, v1, v2; clrexpr(&e1); clrexpr(&e2); op = (int) mp->m_valu; rf = mp->m_type; #if 0 if (!hd64 && rf>X_HD64) rf = 0; #endif if (!r4k_mode && rf > X_R4K_MODE) rf = 0; switch (rf) { case S_INH1: outab(op); break; case S_INH2: outab(0xED); outab(op); break; case S_RET: if (more()) { if ((v1 = admode(CND)) != 0) { outab(op | (v1<<3)); } else { qerr(); } } else { outab(0xC9); } break; case S_PUSH: if (admode(R16X)) { outab(op+0x30); break; } else if ((v1 = admode(R8IP)) != 0) { outab(0xED); if (op == 0xC5) outab(0x76); /* push */ else outab(0x7E); /* pop */ break; } else if ((v1 = admode(R16)) != 0 && (v1 &= 0xFF) != SP) { if (v1 != gixiy(v1)) { outab(op+0x20); break; } outab(op | (v1<<4)); break; } else if (r4k_mode) { if ( (v1 = admode(R32_JKHL)) != 0 ) { outab(JKHL_PG); outab(op+0x30); break; } else if ( (v1 = admode(R32_BCDE)) != 0 ) { outab(BCDE_PG); outab(op+0x30); break; } } aerr(); break; case S_RST: v1 = (int) absexpr(); /* ljm comment - * block RST 00, 08, and 30 b/c those opcodes * are assigned to different instructions in the * rabbit processor */ if ((v1 == 0x00) || (v1 == 0x08) || (v1 == 0x30)) { aerr( ); v1 = 0; } if (v1 & ~0x38) { aerr(); v1 = 0; } outab(op|v1); break; #if 0 /* IM x set interrupt mode on Z-80 */ /* Rabbit processor use the opcode to set interrupt level */ case S_IM: expr(&e1, 0); abscheck(&e1); if (e1.e_addr > 2) { aerr(); e1.e_addr = 0; } outab(op); outab(imtab[(int) e1.e_addr]); break; #endif case S_BIT: expr(&e1, 0); t1 = 0; v1 = (int) e1.e_addr; if (v1 > 7) { ++t1; v1 &= 0x07; } op |= (v1<<3); comma(1); addr(&e2); abscheck(&e1); if (genop(0xCB, op, &e2, 0) || t1) aerr(); break; case S_RL: t1 = 0; t2 = addr(&e2); if ((t2 == S_IMMED) && r4k_mode) { v1 = (int) e2.e_addr; /* v1 should be shift count of 1,2,4, or 8 */ comma(1); clrexpr(&e2); t2 = addr(&e2); if ((t2 != S_R32_BCDE) && (t2 != S_R32_JKHL)) aerr( ); if (v1 == 1) v1 = 0x48; else if (v1 == 2) v1 = 0x49; else if (v1 == 4) v1 = 0x4B; else if ((v1 == 8) && (op < 0x20 /* op is rlc|rrc|rl|rr */)) v1 = 0x4F; else { err('o'); break; } /* 00 rlc, 08 rrc, 10 rl , 18 rr * * 20 sla, 28 sra, 38 srl, [30 sll == sla] */ outab( ((t2 == S_R32_JKHL)?JKHL_PG:BCDE_PG) ); outab(v1 + (op << 1)); break; } else if (more()) { if ((t2 != S_R8) || (e2.e_addr != A)) ++t1; comma(1); clrexpr(&e2); t2 = addr(&e2); } else if (t2 == S_R16) { v2 = (int) e2.e_addr; if ((v2 == DE) && ((op == 0x10 /* rl */) || (op == 0x18 /* rr */))) { outab( 0xF3 - 0x10 + op ); break; } if ((v2 == HL) && (op == 0x18 /* rr */)) { outab( 0xFC ); break; } if (r4k_mode) { if ((v2 == HL) && (op == 0x10 /* rl */)) { outab( 0x42 ); break; } if (((v2 == BC)||(v2 == DE)) && (op < 0x20 /* 00 rlc, 08 rrc, 10 rl, 18 rr */)) { outab( 0x50 + (op >> 3) + ((v2==BC)?0x10:0x00) ); break; } } aerr( ); }