static void samsung_irq_gpio_unmask(unsigned int irq) { struct s3c_gpio_chip *chip = get_irq_chip_data(irq); int group, n, offset, value; group = chip->group; n = samsung_irq_gpio_get_bit(irq, group); offset = (group < 16) ? REG_OFFSET(group) : REG_OFFSET(group - 16); value = __raw_readl(GPIO_BASE(chip) + MASK_OFFSET + offset); value &= ~BIT(n); __raw_writel(value, GPIO_BASE(chip) + MASK_OFFSET + offset); }
static int samsung_irq_gpio_set_type(unsigned int irq, unsigned int type) { struct s3c_gpio_chip *chip = get_irq_chip_data(irq); int group, bit, offset, value, eint_con; struct irq_desc *desc = irq_to_desc(irq); group = chip->group; bit = samsung_irq_gpio_get_bit(irq, group); switch (type) { case IRQ_TYPE_EDGE_RISING: eint_con = SAMSUNG_IRQ_GPIO_EDGE_RISING; break; case IRQ_TYPE_EDGE_FALLING: eint_con = SAMSUNG_IRQ_GPIO_EDGE_FALLING; break; case IRQ_TYPE_EDGE_BOTH: eint_con = SAMSUNG_IRQ_GPIO_EDGE_BOTH; break; case IRQ_TYPE_LEVEL_HIGH: eint_con = SAMSUNG_IRQ_GPIO_LEVEL_HIGH; break; case IRQ_TYPE_LEVEL_LOW: eint_con = SAMSUNG_IRQ_GPIO_LEVEL_LOW; break; case IRQ_TYPE_NONE: printk(KERN_WARNING "No irq type\n"); default: return -EINVAL; } offset = (group < 16) ? REG_OFFSET(group) : REG_OFFSET(group - 16); bit = bit << 2; /* 4 bits offset */ value = __raw_readl(GPIO_BASE(chip) + CON_OFFSET + offset); value &= ~(0xf << bit); value |= (eint_con << bit); __raw_writel(value, GPIO_BASE(chip) + CON_OFFSET + offset); if (type & IRQ_TYPE_EDGE_BOTH) desc->handle_irq = handle_edge_irq; else desc->handle_irq = handle_level_irq; return 0; }
static int pm8916_gpio_set_value(struct udevice *dev, unsigned offset, int value) { struct pm8916_gpio_bank *priv = dev_get_priv(dev); uint32_t gpio_base = priv->pid + REG_OFFSET(offset); /* Set the output value of the gpio */ return pmic_clrsetbits(dev->parent, gpio_base + REG_CTL, REG_CTL_OUTPUT_MASK, !!value); }
static int pm8916_gpio_get_value(struct udevice *dev, unsigned offset) { struct pm8916_gpio_bank *priv = dev_get_priv(dev); uint32_t gpio_base = priv->pid + REG_OFFSET(offset); int reg; reg = pmic_reg_read(dev->parent, gpio_base + REG_STATUS); if (reg < 0) return reg; return !!(reg & REG_STATUS_VAL_MASK); }
static int pm8916_gpio_set_direction(struct udevice *dev, unsigned offset, bool input, int value) { struct pm8916_gpio_bank *priv = dev_get_priv(dev); uint32_t gpio_base = priv->pid + REG_OFFSET(offset); int ret; /* Disable the GPIO */ ret = pmic_clrsetbits(dev->parent, gpio_base + REG_EN_CTL, REG_EN_CTL_ENABLE, 0); if (ret < 0) return ret; /* Select the mode */ if (input) ret = pmic_reg_write(dev->parent, gpio_base + REG_CTL, REG_CTL_MODE_INPUT); else ret = pmic_reg_write(dev->parent, gpio_base + REG_CTL, REG_CTL_MODE_INOUT | (value ? 1 : 0)); if (ret < 0) return ret; /* Set the right pull (no pull) */ ret = pmic_reg_write(dev->parent, gpio_base + REG_DIG_PULL_CTL, REG_DIG_PULL_NO_PU); if (ret < 0) return ret; /* Configure output pin drivers if needed */ if (!input) { /* Select the VIN - VIN0, pin is input so it doesn't matter */ ret = pmic_reg_write(dev->parent, gpio_base + REG_DIG_VIN_CTL, REG_DIG_VIN_VIN0); if (ret < 0) return ret; /* Set the right dig out control */ ret = pmic_reg_write(dev->parent, gpio_base + REG_DIG_OUT_CTL, REG_DIG_OUT_CTL_CMOS | REG_DIG_OUT_CTL_DRIVE_L); if (ret < 0) return ret; } /* Enable the GPIO */ return pmic_clrsetbits(dev->parent, gpio_base + REG_EN_CTL, 0, REG_EN_CTL_ENABLE); }
static void pm8x41_reg_write(uint32_t addr, uint8_t val) { struct pmic_arb_cmd cmd; struct pmic_arb_param param; cmd.address = PERIPH_ID(addr); cmd.offset = REG_OFFSET(addr); cmd.slave_id = SLAVE_ID(addr); cmd.priority = 0; param.buffer = &val; param.size = 1; pmic_arb_write_cmd(&cmd, ¶m); }
/* Local functions */ static uint8_t pm8x41_reg_read(uint32_t addr) { uint8_t val = 0; struct pmic_arb_cmd cmd; struct pmic_arb_param param; cmd.address = PERIPH_ID(addr); cmd.offset = REG_OFFSET(addr); cmd.slave_id = SLAVE_ID(addr); cmd.priority = 0; param.buffer = &val; param.size = 1; pmic_arb_read_cmd(&cmd, ¶m); return val; }
static int pm8916_gpio_get_function(struct udevice *dev, unsigned offset) { struct pm8916_gpio_bank *priv = dev_get_priv(dev); uint32_t gpio_base = priv->pid + REG_OFFSET(offset); int reg; /* Set the output value of the gpio */ reg = pmic_reg_read(dev->parent, gpio_base + REG_CTL); if (reg < 0) return reg; switch (reg & REG_CTL_MODE_MASK) { case REG_CTL_MODE_INPUT: return GPIOF_INPUT; case REG_CTL_MODE_INOUT: /* Fallthrough */ case REG_CTL_MODE_OUTPUT: return GPIOF_OUTPUT; default: return GPIOF_UNKNOWN; } }
#include <machine/arm/tcf/stack-crawl-arm.h> #if ENABLE_ContextMux #include <tcf/framework/cpudefs-mdep-mux.h> #endif #include <tcf/cpudefs-mdep.h> #define REG_OFFSET(name) offsetof(REG_SET, name) RegisterDefinition regs_def[] = { # define REG_FP gp.regs[11] # define REG_IP gp.regs[12] # define REG_SP gp.regs[13] # define REG_LR gp.regs[14] # define REG_PC gp.regs[15] # define REG_CPSR gp.regs[16] { "r0", REG_OFFSET(gp.regs[0]), 4, 0, 0}, { "r1", REG_OFFSET(gp.regs[1]), 4, 1, 1}, { "r2", REG_OFFSET(gp.regs[2]), 4, 2, 2}, { "r3", REG_OFFSET(gp.regs[3]), 4, 3, 3}, { "r4", REG_OFFSET(gp.regs[4]), 4, 4, 4}, { "r5", REG_OFFSET(gp.regs[5]), 4, 5, 5}, { "r6", REG_OFFSET(gp.regs[6]), 4, 6, 6}, { "r7", REG_OFFSET(gp.regs[7]), 4, 7, 7}, { "r8", REG_OFFSET(gp.regs[8]), 4, 8, 8}, { "r9", REG_OFFSET(gp.regs[9]), 4, 9, 9}, { "r10", REG_OFFSET(gp.regs[10]), 4, 10, 10}, { "fp", REG_OFFSET(gp.regs[11]), 4, 11, 11}, { "ip", REG_OFFSET(gp.regs[12]), 4, 12, 12}, { "sp", REG_OFFSET(gp.regs[13]), 4, 13, 13}, { "lr", REG_OFFSET(gp.regs[14]), 4, 14, 14}, { "pc", REG_OFFSET(gp.regs[15]), 4, 15, 15},
static errval_t elf_allocate(void *state, genvaddr_t base, size_t size, uint32_t flags, void **retbase) { errval_t err; struct spawninfo *si = state; // Increase size by space wasted on first page due to page-alignment size_t base_offset = BASE_PAGE_OFFSET(base); size += base_offset; base -= base_offset; // Page-align size = ROUND_UP(size, BASE_PAGE_SIZE); cslot_t vspace_slot = si->elfload_slot; // Allocate the frames size_t sz = 0; for (lpaddr_t offset = 0; offset < size; offset += sz) { sz = 1UL << log2floor(size - offset); struct capref frame = { .cnode = si->segcn, .slot = si->elfload_slot++, }; err = frame_create(frame, sz, NULL); if (err_is_fail(err)) { return err_push(err, LIB_ERR_FRAME_CREATE); } } cslot_t spawn_vspace_slot = si->elfload_slot; cslot_t new_slot_count = si->elfload_slot - vspace_slot; // create copies of the frame capabilities for spawn vspace for (int copy_idx = 0; copy_idx < new_slot_count; copy_idx++) { struct capref frame = { .cnode = si->segcn, .slot = vspace_slot + copy_idx, }; struct capref spawn_frame = { .cnode = si->segcn, .slot = si->elfload_slot++, }; err = cap_copy(spawn_frame, frame); if (err_is_fail(err)) { // TODO: make debug printf printf("cap_copy failed for src_slot = %"PRIuCSLOT", dest_slot = %"PRIuCSLOT"\n", frame.slot, spawn_frame.slot); return err_push(err, LIB_ERR_CAP_COPY); } } /* Map into my vspace */ struct memobj *memobj = malloc(sizeof(struct memobj_anon)); if (!memobj) { return LIB_ERR_MALLOC_FAIL; } struct vregion *vregion = malloc(sizeof(struct vregion)); if (!vregion) { return LIB_ERR_MALLOC_FAIL; } // Create the objects err = memobj_create_anon((struct memobj_anon*)memobj, size, 0); if (err_is_fail(err)) { return err_push(err, LIB_ERR_MEMOBJ_CREATE_ANON); } err = vregion_map(vregion, get_current_vspace(), memobj, 0, size, VREGION_FLAGS_READ_WRITE); if (err_is_fail(err)) { return err_push(err, LIB_ERR_VSPACE_MAP); } for (lvaddr_t offset = 0; offset < size; offset += sz) { sz = 1UL << log2floor(size - offset); struct capref frame = { .cnode = si->segcn, .slot = vspace_slot++, }; genvaddr_t genvaddr = vspace_lvaddr_to_genvaddr(offset); err = memobj->f.fill(memobj, genvaddr, frame, sz); if (err_is_fail(err)) { return err_push(err, LIB_ERR_MEMOBJ_FILL); } err = memobj->f.pagefault(memobj, vregion, offset, 0); if (err_is_fail(err)) { DEBUG_ERR(err, "lib_err_memobj_pagefault_handler"); return err_push(err, LIB_ERR_MEMOBJ_PAGEFAULT_HANDLER); } } /* Map into spawn vspace */ struct memobj *spawn_memobj = NULL; struct vregion *spawn_vregion = NULL; err = spawn_vspace_map_anon_fixed_attr(si, base, size, &spawn_vregion, &spawn_memobj, elf_to_vregion_flags(flags)); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_VSPACE_MAP); } for (lvaddr_t offset = 0; offset < size; offset += sz) { sz = 1UL << log2floor(size - offset); struct capref frame = { .cnode = si->segcn, .slot = spawn_vspace_slot++, }; genvaddr_t genvaddr = vspace_lvaddr_to_genvaddr(offset); err = memobj->f.fill(spawn_memobj, genvaddr, frame, sz); if (err_is_fail(err)) { return err_push(err, LIB_ERR_MEMOBJ_FILL); } err = spawn_memobj->f.pagefault(spawn_memobj, spawn_vregion, offset, 0); if (err_is_fail(err)) { DEBUG_ERR(err, "lib_err_memobj_pagefault_handler"); return err_push(err, LIB_ERR_MEMOBJ_PAGEFAULT_HANDLER); } } genvaddr_t genvaddr = vregion_get_base_addr(vregion) + base_offset; *retbase = (void*)vspace_genvaddr_to_lvaddr(genvaddr); return SYS_ERR_OK; } /** * \brief Load the elf image */ errval_t spawn_arch_load(struct spawninfo *si, lvaddr_t binary, size_t binary_size, genvaddr_t *entry, void** arch_info) { errval_t err; // Reset the elfloader_slot si->elfload_slot = 0; struct capref cnode_cap = { .cnode = si->rootcn, .slot = ROOTCN_SLOT_SEGCN, }; err = cnode_create_raw(cnode_cap, &si->segcn, DEFAULT_CNODE_SLOTS, NULL); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_CREATE_SEGCN); } // TLS is NYI si->tls_init_base = 0; si->tls_init_len = si->tls_total_len = 0; // Load the binary err = elf_load(EM_HOST, elf_allocate, si, binary, binary_size, entry); if (err_is_fail(err)) { return err; } struct Elf32_Shdr* got_shdr = elf32_find_section_header_name(binary, binary_size, ".got"); if (got_shdr) { *arch_info = (void*)got_shdr->sh_addr; } else { return SPAWN_ERR_LOAD; } return SYS_ERR_OK; } void spawn_arch_set_registers(void *arch_load_info, dispatcher_handle_t handle, arch_registers_state_t *enabled_area, arch_registers_state_t *disabled_area) { assert(arch_load_info != NULL); uintptr_t got_base = (uintptr_t)arch_load_info; struct dispatcher_shared_arm* disp_arm = get_dispatcher_shared_arm(handle); disp_arm->got_base = got_base; enabled_area->regs[REG_OFFSET(PIC_REGISTER)] = got_base; disabled_area->regs[REG_OFFSET(PIC_REGISTER)] = got_base; #ifndef __ARM_ARCH_7M__ //armv7-m does not support these flags enabled_area->named.cpsr = CPSR_F_MASK | ARM_MODE_USR; disabled_area->named.cpsr = CPSR_F_MASK | ARM_MODE_USR; #endif }
BOOLEAN HalpInitializeInterrupts ( VOID ) /*++ Routine Description: This function initializes interrupts for a Jazz or Duo MIPS system. N.B. This function is only called during phase 0 initialization. Arguments: None. Return Value: A value of TRUE is returned if the initialization is successfully completed. Otherwise a value of FALSE is returned. --*/ { ULONG DataLong; ULONG Index; PKPRCB Prcb; ULONG Address; ENTRYLO HalpPte[2]; TIMER_CONTROL timerControl; // // Get the address of the processor control block for the current // processor. // Prcb = PCR->Prcb; // // Initialize the IRQL translation tables in the PCR. These tables are // used by the interrupt dispatcher to determine the new IRQL and the // mask value that is to be loaded into the PSR. They are also used by // the routines that raise and lower IRQL to load a new mask value into // the PSR. // for (Index = 0; Index < sizeof(HalpIrqlMask); Index += 1) { PCR->IrqlMask[Index] = HalpIrqlMask[Index]; } for (Index = 0; Index < sizeof(HalpIrqlTable); Index += 1) { PCR->IrqlTable[Index] = HalpIrqlTable[Index]; } // // Disable all system level interrupts which // includes all IO (PCI/EISA) device interrupts. // WRITE_REGISTER_ULONG(HalpPmpIntCtrl, 0); // // If processor 0 is being initialized, then clear all builtin device // interrupt enables. // if (Prcb->Number == 0) { HalpBuiltinInterruptEnable = 0; } // // Read IntStatus // DataLong = READ_REGISTER_ULONG(HalpPmpIntStatus) & INT_STATUS_AMASK; // // If there are any pending interrupts to processor A, // then read the *Ack registers to clear the offending // condition. We will need to map registers on-the-fly // here iff there are any pending interrupts to be serviced. // if (DataLong) { do { // // Clear pending IO interrupts // if (DataLong & INT_STATUS_IOA) { HalpMapSysCtrlReg(PMP(IO_INT_ACK_PHYSICAL_BASE), 0, SYS_CONTROL_VIRTUAL_BASE); READ_REGISTER_ULONG(SYS_CONTROL_VIRTUAL_BASE + REG_OFFSET(PMP(IO_INT_ACK_PHYSICAL_BASE))); HalpUnMapSysCtrlReg(); } // // Clear pending IP interrupts // if (DataLong & INT_STATUS_IPA) { HalpMapSysCtrlReg(PMP(IP_INT_ACK_PHYSICAL_BASE), 0, SYS_CONTROL_VIRTUAL_BASE); READ_REGISTER_ULONG(SYS_CONTROL_VIRTUAL_BASE + REG_OFFSET(PMP(IP_INT_ACK_PHYSICAL_BASE))); HalpUnMapSysCtrlReg(); } // // Clear pending PCI interrupts // if (DataLong & (INT_STATUS_PA | INT_STATUS_PNI)) { HalpMapSysCtrlReg(PMP(PCI_ERR_ACK_PHYSICAL_BASE), 0, SYS_CONTROL_VIRTUAL_BASE); READ_REGISTER_ULONG(SYS_CONTROL_VIRTUAL_BASE + REG_OFFSET(PMP(PCI_ERR_ACK_PHYSICAL_BASE))); HalpUnMapSysCtrlReg(); } // // Clear pending MCU interrupts // if (DataLong & (INT_STATUS_MA | INT_STATUS_MNI)) { HalpMapSysCtrlReg(PMP(MEM_ERR_ACK_PHYSICAL_BASE), 0, SYS_CONTROL_VIRTUAL_BASE); READ_REGISTER_ULONG(SYS_CONTROL_VIRTUAL_BASE + REG_OFFSET(PMP(MEM_ERR_ACK_PHYSICAL_BASE))); HalpUnMapSysCtrlReg(); } // // Clear pending Timer interrupts // if (DataLong & INT_STATUS_ITA) { HalpMapSysCtrlReg(PMP(INT_CLR_CTRL_PHYSICAL_BASE), 0, SYS_CONTROL_VIRTUAL_BASE); READ_REGISTER_ULONG(SYS_CONTROL_VIRTUAL_BASE + REG_OFFSET(PMP(INT_CLR_CTRL_PHYSICAL_BASE))); HalpUnMapSysCtrlReg(); } } while ((READ_REGISTER_ULONG(HalpPmpIntStatus) & INT_STATUS_AMASK) != 0); } // // For FALCON: all interrupts, except the R4x00 timer and // software interrupts, come into the kernel at the same // level due to the manner in which interrupts are delivered // to the processor and controlled by the IP field in the // R4x00 cause register. // // This means that we need a master interrupt handler whose // job is to (1) determine the source of the interrupt and // (2) invoke the correct interrupt handler to service the // request. // // Instead of managing a separate data structure for interrupt // vectors, we will still install all interupt handlers at their // normal positions within the IDT, eventhough they will be not // be directly invoked by the kernel but rather by the master // interrupt handler named HalpInterruptDispatch. Please // refere to the fxintr.s file for more details on how this scheme // will work. // PCR->InterruptRoutine[FALCON_LEVEL] = HalpInterruptDispatch; // // Likewise, we need a similar routine for IO device interrupts // to transfer control to the correct handler based on the IRQ // vector returned by the 82374. This handler is the first level // handler in the HAL for any IO interrupt, regardless of whether // the interrupt is from a PCI device or an EISA/ISA device. // PCR->InterruptRoutine[IO_DEVICE_LEVEL] = HalpIoInterruptDispatch; // // We also need to install the Memory and PCI interrupt handlers // that deal with errors such as parity and ECC, etc. These handlers // are invoked by the master interrupt handler but are in the IDT // for completeness. These same handlers should serve as the error // handlers for bus errors (i.e., synchronous errors as opposed to // asynchronous interrupts). // PCR->InterruptRoutine[MEMORY_LEVEL] = HalpMemoryInterrupt; PCR->InterruptRoutine[PCI_LEVEL] = HalpPciInterrupt; // // Install IP interrupt routine in PCR structure. // PCR->InterruptRoutine[IPI_LEVEL] = HalpIpiInterrupt; // // If processor 0 is being initialized, then connect the interval timer // interrupt to the stall interrupt routine so the stall execution count // can be computed during phase 1 initialization. Otherwise, connect the // interval timer interrupt to the appropriate interrupt service routine // and set stall execution count from the computation made on processor // 0. // PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpStallInterrupt; PCR->InterruptRoutine[IRQL0_VECTOR] = HalpStallInterrupt; // // If processor 0 is being initialized, then connect the count/compare // interrupt to the count interrupt routine to handle early count/compare // interrupts during phase 1 initialization. Otherwise, connect the // count\comapre interrupt to the appropriate interrupt service routine. // PCR->InterruptRoutine[PROFILE_LEVEL] = HalpCountInterrupt; // // Initialize the interval timer to interrupt at the specified interval. // // Note that for the first version of the PMP chip, the timer control // and the interrupt signal will only be controllable through the 82374 // and visible through the standard IRQ* signals. However, in the second // version of the PMP chip, the interrupt signal will actually be a // separate interrupt signal not part of the IRQ architecture of the // 82374. This signal will actually be delivered by Timer 1, Counter 2 // in the 82374 which is normally used to generate speaker tone(s). // We can play this trick because this timer runs off the same clock as // the normal system timer (Timer 1, Counter 0). The difference between // the two timers are that the system timer is wired to IRQ0 permanently // and is always enabled, while the speaker timer is not part of the // IRQ architecture and must be enabled by software through port 0x61 // (NMI Status and Control Register). // // // For the first version of the PMP chip, we actually need to initialize // the cascaded interrupt controllers in the 82374 before we can enable // interrupts for the interval timer (or any other IO device). This is // because the interval timer circuitry is in the 82374 and is part of // the standard IRQ* architecture. In the second version of the PMP chip, // the timer interrupt is a separate signal and we can avoid having to // initialize the 82374 interrupt controllers during this phase. // // // Map the system timer control registers // located in the 82374 through EISA control // space using one of the wired entries in // the TLB. We will relinquish this entry when // HalpMapIoSpace() is called and maps Eisa // control space using MmMapIoSpace(). // HalpMapSysCtrlReg(EISA_CONTROL_PHYSICAL_BASE, 0, SYS_CONTROL_VIRTUAL_BASE); HalpEisaControlBase = (PVOID)SYS_CONTROL_VIRTUAL_BASE; // // Initialize the interrupt controllers. // HalpInitializeEisaInterrupts((PEISA_CONTROL)HalpEisaControlBase); // // Initialize interval timer // // Timer 1, Counter 2, Mode 3 (Square Wave), Binary Countdown // timerControl.BcdMode = 0; timerControl.Mode = TM_SQUARE_WAVE; timerControl.SelectByte = SB_LSB_THEN_MSB; if ( HalpPmpRevision < 3 ) { // // PMP V2 uses Counter 0, IRQ0. // timerControl.SelectCounter = SELECT_COUNTER_0; WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpEisaControlBase)->CommandMode1, *((PUCHAR) &timerControl)); // // Set the system clock timer to the correct frequency. // WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpEisaControlBase)->Timer1, (UCHAR)CLOCK_INTERVAL); WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpEisaControlBase)->Timer1, (UCHAR)(CLOCK_INTERVAL >> 8)); } else {
int main() { printf("clken1 offset: %d\n",REG_OFFSET(regs0->clken1)); return 0; }
#include "fbsd-nat.h" #include "amd64-tdep.h" #include "amd64-nat.h" #include "amd64bsd-nat.h" #include "i386-nat.h" /* Offset in `struct reg' where MEMBER is stored. */ #define REG_OFFSET(member) offsetof (struct reg, member) /* At amd64fbsd64_r_reg_offset[REGNUM] you'll find the offset in `struct reg' location where the GDB register REGNUM is stored. Unsupported registers are marked with `-1'. */ static int amd64fbsd64_r_reg_offset[] = { REG_OFFSET (r_rax), REG_OFFSET (r_rbx), REG_OFFSET (r_rcx), REG_OFFSET (r_rdx), REG_OFFSET (r_rsi), REG_OFFSET (r_rdi), REG_OFFSET (r_rbp), REG_OFFSET (r_rsp), REG_OFFSET (r_r8), REG_OFFSET (r_r9), REG_OFFSET (r_r10), REG_OFFSET (r_r11), REG_OFFSET (r_r12), REG_OFFSET (r_r13), REG_OFFSET (r_r14), REG_OFFSET (r_r15),
#define VCPU_NR_MODES 6 #define REG_OFFSET(_reg) \ (offsetof(struct user_pt_regs, _reg) / sizeof(unsigned long)) #define USR_REG_OFFSET(R) REG_OFFSET(compat_usr(R)) static const unsigned long vcpu_reg_offsets[VCPU_NR_MODES][16] = { /* USR Registers */ { USR_REG_OFFSET(0), USR_REG_OFFSET(1), USR_REG_OFFSET(2), USR_REG_OFFSET(3), USR_REG_OFFSET(4), USR_REG_OFFSET(5), USR_REG_OFFSET(6), USR_REG_OFFSET(7), USR_REG_OFFSET(8), USR_REG_OFFSET(9), USR_REG_OFFSET(10), USR_REG_OFFSET(11), USR_REG_OFFSET(12), USR_REG_OFFSET(13), USR_REG_OFFSET(14), REG_OFFSET(pc) }, /* FIQ Registers */ { USR_REG_OFFSET(0), USR_REG_OFFSET(1), USR_REG_OFFSET(2), USR_REG_OFFSET(3), USR_REG_OFFSET(4), USR_REG_OFFSET(5), USR_REG_OFFSET(6), USR_REG_OFFSET(7), REG_OFFSET(compat_r8_fiq), /* r8 */ REG_OFFSET(compat_r9_fiq), /* r9 */ REG_OFFSET(compat_r10_fiq), /* r10 */ REG_OFFSET(compat_r11_fiq), /* r11 */ REG_OFFSET(compat_r12_fiq), /* r12 */ REG_OFFSET(compat_sp_fiq), /* r13 */ REG_OFFSET(compat_lr_fiq), /* r14 */ REG_OFFSET(pc)
static struct sal_ret_values sal_emulator (long index, unsigned long in1, unsigned long in2, unsigned long in3, unsigned long in4, unsigned long in5, unsigned long in6, unsigned long in7) { long r9 = 0; long r10 = 0; long r11 = 0; long status; /* * Don't do a "switch" here since that gives us code that * isn't self-relocatable. */ status = 0; if (index == SAL_FREQ_BASE) { switch (in1) { case SAL_FREQ_BASE_PLATFORM: r9 = 200000000; break; case SAL_FREQ_BASE_INTERVAL_TIMER: /* * Is this supposed to be the cr.itc frequency * or something platform specific? The SAL * doc ain't exactly clear on this... */ r9 = 700000000; break; case SAL_FREQ_BASE_REALTIME_CLOCK: r9 = 1; break; default: status = -1; break; } } else if (index == SAL_SET_VECTORS) { ; } else if (index == SAL_GET_STATE_INFO) { ; } else if (index == SAL_GET_STATE_INFO_SIZE) { ; } else if (index == SAL_CLEAR_STATE_INFO) { ; } else if (index == SAL_MC_RENDEZ) { ; } else if (index == SAL_MC_SET_PARAMS) { ; } else if (index == SAL_CACHE_FLUSH) { ; } else if (index == SAL_CACHE_INIT) { ; #ifdef CONFIG_PCI } else if (index == SAL_PCI_CONFIG_READ) { /* * in1 contains the PCI configuration address and in2 * the size of the read. The value that is read is * returned via the general register r9. */ outl(BUILD_CMD(in1), 0xCF8); if (in2 == 1) /* Reading byte */ r9 = inb(0xCFC + ((REG_OFFSET(in1) & 3))); else if (in2 == 2) /* Reading word */ r9 = inw(0xCFC + ((REG_OFFSET(in1) & 2))); else /* Reading dword */ r9 = inl(0xCFC); status = PCIBIOS_SUCCESSFUL; } else if (index == SAL_PCI_CONFIG_WRITE) { /* * in1 contains the PCI configuration address, in2 the * size of the write, and in3 the actual value to be * written out. */ outl(BUILD_CMD(in1), 0xCF8); if (in2 == 1) /* Writing byte */ outb(in3, 0xCFC + ((REG_OFFSET(in1) & 3))); else if (in2 == 2) /* Writing word */ outw(in3, 0xCFC + ((REG_OFFSET(in1) & 2))); else /* Writing dword */ outl(in3, 0xCFC); status = PCIBIOS_SUCCESSFUL; #endif /* CONFIG_PCI */ } else if (index == SAL_UPDATE_PAL) { ; } else { status = -1; } return ((struct sal_ret_values) {status, r9, r10, r11});
static void print_rtx (const_rtx in_rtx) { int i = 0; int j; const char *format_ptr; int is_insn; if (sawclose) { if (flag_simple) fputc (' ', outfile); else fprintf (outfile, "\n%s%*s", print_rtx_head, indent * 2, ""); sawclose = 0; } if (in_rtx == 0) { fputs ("(nil)", outfile); sawclose = 1; return; } else if (GET_CODE (in_rtx) > NUM_RTX_CODE) { fprintf (outfile, "(??? bad code %d\n%s%*s)", GET_CODE (in_rtx), print_rtx_head, indent * 2, ""); sawclose = 1; return; } is_insn = INSN_P (in_rtx); /* Print name of expression code. */ if (flag_simple && CONST_INT_P (in_rtx)) fputc ('(', outfile); else fprintf (outfile, "(%s", GET_RTX_NAME (GET_CODE (in_rtx))); if (! flag_simple) { if (RTX_FLAG (in_rtx, in_struct)) fputs ("/s", outfile); if (RTX_FLAG (in_rtx, volatil)) fputs ("/v", outfile); if (RTX_FLAG (in_rtx, unchanging)) fputs ("/u", outfile); if (RTX_FLAG (in_rtx, frame_related)) fputs ("/f", outfile); if (RTX_FLAG (in_rtx, jump)) fputs ("/j", outfile); if (RTX_FLAG (in_rtx, call)) fputs ("/c", outfile); if (RTX_FLAG (in_rtx, return_val)) fputs ("/i", outfile); /* Print REG_NOTE names for EXPR_LIST and INSN_LIST. */ if ((GET_CODE (in_rtx) == EXPR_LIST || GET_CODE (in_rtx) == INSN_LIST || GET_CODE (in_rtx) == INT_LIST) && (int)GET_MODE (in_rtx) < REG_NOTE_MAX) fprintf (outfile, ":%s", GET_REG_NOTE_NAME (GET_MODE (in_rtx))); /* For other rtl, print the mode if it's not VOID. */ else if (GET_MODE (in_rtx) != VOIDmode) fprintf (outfile, ":%s", GET_MODE_NAME (GET_MODE (in_rtx))); #ifndef GENERATOR_FILE if (GET_CODE (in_rtx) == VAR_LOCATION) { if (TREE_CODE (PAT_VAR_LOCATION_DECL (in_rtx)) == STRING_CST) fputs (" <debug string placeholder>", outfile); else print_mem_expr (outfile, PAT_VAR_LOCATION_DECL (in_rtx)); fputc (' ', outfile); print_rtx (PAT_VAR_LOCATION_LOC (in_rtx)); if (PAT_VAR_LOCATION_STATUS (in_rtx) == VAR_INIT_STATUS_UNINITIALIZED) fprintf (outfile, " [uninit]"); sawclose = 1; i = GET_RTX_LENGTH (VAR_LOCATION); } #endif } #ifndef GENERATOR_FILE if (CONST_DOUBLE_AS_FLOAT_P (in_rtx)) i = 5; #endif /* Get the format string and skip the first elements if we have handled them already. */ format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx)) + i; for (; i < GET_RTX_LENGTH (GET_CODE (in_rtx)); i++) switch (*format_ptr++) { const char *str; case 'T': str = XTMPL (in_rtx, i); goto string; case 'S': case 's': str = XSTR (in_rtx, i); string: if (str == 0) fputs (" \"\"", outfile); else fprintf (outfile, " (\"%s\")", str); sawclose = 1; break; /* 0 indicates a field for internal use that should not be printed. An exception is the third field of a NOTE, where it indicates that the field has several different valid contents. */ case '0': if (i == 1 && REG_P (in_rtx)) { if (REGNO (in_rtx) != ORIGINAL_REGNO (in_rtx)) fprintf (outfile, " [%d]", ORIGINAL_REGNO (in_rtx)); } #ifndef GENERATOR_FILE else if (i == 1 && GET_CODE (in_rtx) == SYMBOL_REF) { int flags = SYMBOL_REF_FLAGS (in_rtx); if (flags) fprintf (outfile, " [flags %#x]", flags); } else if (i == 2 && GET_CODE (in_rtx) == SYMBOL_REF) { tree decl = SYMBOL_REF_DECL (in_rtx); if (decl) print_node_brief (outfile, "", decl, dump_flags); } #endif else if (i == 4 && NOTE_P (in_rtx)) { switch (NOTE_KIND (in_rtx)) { case NOTE_INSN_EH_REGION_BEG: case NOTE_INSN_EH_REGION_END: if (flag_dump_unnumbered) fprintf (outfile, " #"); else fprintf (outfile, " %d", NOTE_EH_HANDLER (in_rtx)); sawclose = 1; break; case NOTE_INSN_BLOCK_BEG: case NOTE_INSN_BLOCK_END: #ifndef GENERATOR_FILE dump_addr (outfile, " ", NOTE_BLOCK (in_rtx)); #endif sawclose = 1; break; case NOTE_INSN_BASIC_BLOCK: { #ifndef GENERATOR_FILE basic_block bb = NOTE_BASIC_BLOCK (in_rtx); if (bb != 0) fprintf (outfile, " [bb %d]", bb->index); #endif break; } case NOTE_INSN_DELETED_LABEL: case NOTE_INSN_DELETED_DEBUG_LABEL: { const char *label = NOTE_DELETED_LABEL_NAME (in_rtx); if (label) fprintf (outfile, " (\"%s\")", label); else fprintf (outfile, " \"\""); } break; case NOTE_INSN_SWITCH_TEXT_SECTIONS: { #ifndef GENERATOR_FILE basic_block bb = NOTE_BASIC_BLOCK (in_rtx); if (bb != 0) fprintf (outfile, " [bb %d]", bb->index); #endif break; } case NOTE_INSN_VAR_LOCATION: case NOTE_INSN_CALL_ARG_LOCATION: #ifndef GENERATOR_FILE fputc (' ', outfile); print_rtx (NOTE_VAR_LOCATION (in_rtx)); #endif break; case NOTE_INSN_CFI: #ifndef GENERATOR_FILE fputc ('\n', outfile); output_cfi_directive (outfile, NOTE_CFI (in_rtx)); fputc ('\t', outfile); #endif break; default: break; } } else if (i == 8 && JUMP_P (in_rtx) && JUMP_LABEL (in_rtx) != NULL) { /* Output the JUMP_LABEL reference. */ fprintf (outfile, "\n%s%*s -> ", print_rtx_head, indent * 2, ""); if (GET_CODE (JUMP_LABEL (in_rtx)) == RETURN) fprintf (outfile, "return"); else if (GET_CODE (JUMP_LABEL (in_rtx)) == SIMPLE_RETURN) fprintf (outfile, "simple_return"); else fprintf (outfile, "%d", INSN_UID (JUMP_LABEL (in_rtx))); } else if (i == 0 && GET_CODE (in_rtx) == VALUE) { #ifndef GENERATOR_FILE cselib_val *val = CSELIB_VAL_PTR (in_rtx); fprintf (outfile, " %u:%u", val->uid, val->hash); dump_addr (outfile, " @", in_rtx); dump_addr (outfile, "/", (void*)val); #endif } else if (i == 0 && GET_CODE (in_rtx) == DEBUG_EXPR) { #ifndef GENERATOR_FILE fprintf (outfile, " D#%i", DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (in_rtx))); #endif } else if (i == 0 && GET_CODE (in_rtx) == ENTRY_VALUE) { indent += 2; if (!sawclose) fprintf (outfile, " "); print_rtx (ENTRY_VALUE_EXP (in_rtx)); indent -= 2; } break; case 'e': do_e: indent += 2; if (i == 7 && INSN_P (in_rtx)) /* Put REG_NOTES on their own line. */ fprintf (outfile, "\n%s%*s", print_rtx_head, indent * 2, ""); if (!sawclose) fprintf (outfile, " "); print_rtx (XEXP (in_rtx, i)); indent -= 2; break; case 'E': case 'V': indent += 2; if (sawclose) { fprintf (outfile, "\n%s%*s", print_rtx_head, indent * 2, ""); sawclose = 0; } fputs (" [", outfile); if (NULL != XVEC (in_rtx, i)) { indent += 2; if (XVECLEN (in_rtx, i)) sawclose = 1; for (j = 0; j < XVECLEN (in_rtx, i); j++) print_rtx (XVECEXP (in_rtx, i, j)); indent -= 2; } if (sawclose) fprintf (outfile, "\n%s%*s", print_rtx_head, indent * 2, ""); fputs ("]", outfile); sawclose = 1; indent -= 2; break; case 'w': if (! flag_simple) fprintf (outfile, " "); fprintf (outfile, HOST_WIDE_INT_PRINT_DEC, XWINT (in_rtx, i)); if (! flag_simple) fprintf (outfile, " [" HOST_WIDE_INT_PRINT_HEX "]", (unsigned HOST_WIDE_INT) XWINT (in_rtx, i)); break; case 'i': if (i == 5 && INSN_P (in_rtx)) { #ifndef GENERATOR_FILE /* Pretty-print insn locations. Ignore scoping as it is mostly redundant with line number information and do not print anything when there is no location information available. */ if (INSN_LOCATION (in_rtx) && insn_file (in_rtx)) fprintf(outfile, " %s:%i", insn_file (in_rtx), insn_line (in_rtx)); #endif } else if (i == 6 && GET_CODE (in_rtx) == ASM_OPERANDS) { #ifndef GENERATOR_FILE fprintf (outfile, " %s:%i", LOCATION_FILE (ASM_OPERANDS_SOURCE_LOCATION (in_rtx)), LOCATION_LINE (ASM_OPERANDS_SOURCE_LOCATION (in_rtx))); #endif } else if (i == 1 && GET_CODE (in_rtx) == ASM_INPUT) { #ifndef GENERATOR_FILE fprintf (outfile, " %s:%i", LOCATION_FILE (ASM_INPUT_SOURCE_LOCATION (in_rtx)), LOCATION_LINE (ASM_INPUT_SOURCE_LOCATION (in_rtx))); #endif } else if (i == 6 && NOTE_P (in_rtx)) { /* This field is only used for NOTE_INSN_DELETED_LABEL, and other times often contains garbage from INSN->NOTE death. */ if (NOTE_KIND (in_rtx) == NOTE_INSN_DELETED_LABEL || NOTE_KIND (in_rtx) == NOTE_INSN_DELETED_DEBUG_LABEL) fprintf (outfile, " %d", XINT (in_rtx, i)); } #if !defined(GENERATOR_FILE) && NUM_UNSPECV_VALUES > 0 else if (i == 1 && GET_CODE (in_rtx) == UNSPEC_VOLATILE && XINT (in_rtx, 1) >= 0 && XINT (in_rtx, 1) < NUM_UNSPECV_VALUES) fprintf (outfile, " %s", unspecv_strings[XINT (in_rtx, 1)]); #endif #if !defined(GENERATOR_FILE) && NUM_UNSPEC_VALUES > 0 else if (i == 1 && (GET_CODE (in_rtx) == UNSPEC || GET_CODE (in_rtx) == UNSPEC_VOLATILE) && XINT (in_rtx, 1) >= 0 && XINT (in_rtx, 1) < NUM_UNSPEC_VALUES) fprintf (outfile, " %s", unspec_strings[XINT (in_rtx, 1)]); #endif else { int value = XINT (in_rtx, i); const char *name; #ifndef GENERATOR_FILE if (REG_P (in_rtx) && (unsigned) value < FIRST_PSEUDO_REGISTER) fprintf (outfile, " %d %s", value, reg_names[value]); else if (REG_P (in_rtx) && (unsigned) value <= LAST_VIRTUAL_REGISTER) { if (value == VIRTUAL_INCOMING_ARGS_REGNUM) fprintf (outfile, " %d virtual-incoming-args", value); else if (value == VIRTUAL_STACK_VARS_REGNUM) fprintf (outfile, " %d virtual-stack-vars", value); else if (value == VIRTUAL_STACK_DYNAMIC_REGNUM) fprintf (outfile, " %d virtual-stack-dynamic", value); else if (value == VIRTUAL_OUTGOING_ARGS_REGNUM) fprintf (outfile, " %d virtual-outgoing-args", value); else if (value == VIRTUAL_CFA_REGNUM) fprintf (outfile, " %d virtual-cfa", value); else if (value == VIRTUAL_PREFERRED_STACK_BOUNDARY_REGNUM) fprintf (outfile, " %d virtual-preferred-stack-boundary", value); else fprintf (outfile, " %d virtual-reg-%d", value, value-FIRST_VIRTUAL_REGISTER); } else #endif if (flag_dump_unnumbered && (is_insn || NOTE_P (in_rtx))) fputc ('#', outfile); else fprintf (outfile, " %d", value); #ifndef GENERATOR_FILE if (REG_P (in_rtx) && REG_ATTRS (in_rtx)) { fputs (" [", outfile); if (ORIGINAL_REGNO (in_rtx) != REGNO (in_rtx)) fprintf (outfile, "orig:%i", ORIGINAL_REGNO (in_rtx)); if (REG_EXPR (in_rtx)) print_mem_expr (outfile, REG_EXPR (in_rtx)); if (REG_OFFSET (in_rtx)) fprintf (outfile, "+" HOST_WIDE_INT_PRINT_DEC, REG_OFFSET (in_rtx)); fputs (" ]", outfile); } #endif if (is_insn && &INSN_CODE (in_rtx) == &XINT (in_rtx, i) && XINT (in_rtx, i) >= 0 && (name = get_insn_name (XINT (in_rtx, i))) != NULL) fprintf (outfile, " {%s}", name); sawclose = 0; } break; /* Print NOTE_INSN names rather than integer codes. */ case 'n': fprintf (outfile, " %s", GET_NOTE_INSN_NAME (XINT (in_rtx, i))); sawclose = 0; break; case 'u': if (XEXP (in_rtx, i) != NULL) { rtx sub = XEXP (in_rtx, i); enum rtx_code subc = GET_CODE (sub); if (GET_CODE (in_rtx) == LABEL_REF) { if (subc == NOTE && NOTE_KIND (sub) == NOTE_INSN_DELETED_LABEL) { if (flag_dump_unnumbered) fprintf (outfile, " [# deleted]"); else fprintf (outfile, " [%d deleted]", INSN_UID (sub)); sawclose = 0; break; } if (subc != CODE_LABEL) goto do_e; } if (flag_dump_unnumbered || (flag_dump_unnumbered_links && (i == 1 || i == 2) && (INSN_P (in_rtx) || NOTE_P (in_rtx) || LABEL_P (in_rtx) || BARRIER_P (in_rtx)))) fputs (" #", outfile); else fprintf (outfile, " %d", INSN_UID (sub)); } else fputs (" 0", outfile); sawclose = 0; break; case 't': #ifndef GENERATOR_FILE if (i == 0 && GET_CODE (in_rtx) == DEBUG_IMPLICIT_PTR) print_mem_expr (outfile, DEBUG_IMPLICIT_PTR_DECL (in_rtx)); else if (i == 0 && GET_CODE (in_rtx) == DEBUG_PARAMETER_REF) print_mem_expr (outfile, DEBUG_PARAMETER_REF_DECL (in_rtx)); else dump_addr (outfile, " ", XTREE (in_rtx, i)); #endif break; case '*': fputs (" Unknown", outfile); sawclose = 0; break; case 'B': #ifndef GENERATOR_FILE if (XBBDEF (in_rtx, i)) fprintf (outfile, " %i", XBBDEF (in_rtx, i)->index); #endif break; default: gcc_unreachable (); } switch (GET_CODE (in_rtx)) { #ifndef GENERATOR_FILE case MEM: if (__builtin_expect (final_insns_dump_p, false)) fprintf (outfile, " ["); else fprintf (outfile, " [" HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT) MEM_ALIAS_SET (in_rtx)); if (MEM_EXPR (in_rtx)) print_mem_expr (outfile, MEM_EXPR (in_rtx)); if (MEM_OFFSET_KNOWN_P (in_rtx)) fprintf (outfile, "+" HOST_WIDE_INT_PRINT_DEC, MEM_OFFSET (in_rtx)); if (MEM_SIZE_KNOWN_P (in_rtx)) fprintf (outfile, " S" HOST_WIDE_INT_PRINT_DEC, MEM_SIZE (in_rtx)); if (MEM_ALIGN (in_rtx) != 1) fprintf (outfile, " A%u", MEM_ALIGN (in_rtx)); if (!ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (in_rtx))) fprintf (outfile, " AS%u", MEM_ADDR_SPACE (in_rtx)); fputc (']', outfile); break; case CONST_DOUBLE: if (FLOAT_MODE_P (GET_MODE (in_rtx))) { char s[60]; real_to_decimal (s, CONST_DOUBLE_REAL_VALUE (in_rtx), sizeof (s), 0, 1); fprintf (outfile, " %s", s); real_to_hexadecimal (s, CONST_DOUBLE_REAL_VALUE (in_rtx), sizeof (s), 0, 1); fprintf (outfile, " [%s]", s); } break; #endif case CODE_LABEL: fprintf (outfile, " [%d uses]", LABEL_NUSES (in_rtx)); switch (LABEL_KIND (in_rtx)) { case LABEL_NORMAL: break; case LABEL_STATIC_ENTRY: fputs (" [entry]", outfile); break; case LABEL_GLOBAL_ENTRY: fputs (" [global entry]", outfile); break; case LABEL_WEAK_ENTRY: fputs (" [weak entry]", outfile); break; default: gcc_unreachable (); } break; default: break; } fputc (')', outfile); sawclose = 1; }
#include "gnu-nat.h" #include "i387-tdep.h" #ifdef HAVE_SYS_PROCFS_H # include <sys/procfs.h> # include "gregset.h" #endif /* Offset to the thread_state_t location where REG is stored. */ #define REG_OFFSET(reg) offsetof (struct i386_thread_state, reg) /* At REG_OFFSET[N] is the offset to the thread_state_t location where the GDB register N is stored. */ static int reg_offset[] = { REG_OFFSET (eax), REG_OFFSET (ecx), REG_OFFSET (edx), REG_OFFSET (ebx), REG_OFFSET (uesp), REG_OFFSET (ebp), REG_OFFSET (esi), REG_OFFSET (edi), REG_OFFSET (eip), REG_OFFSET (efl), REG_OFFSET (cs), REG_OFFSET (ss), REG_OFFSET (ds), REG_OFFSET (es), REG_OFFSET (fs), REG_OFFSET (gs) }; #define REG_ADDR(state, regnum) ((char *)(state) + reg_offset[regnum]) #define CREG_ADDR(state, regnum) ((const char *)(state) + reg_offset[regnum]) /* Get the whole floating-point state of THREAD and record the values of the corresponding (pseudo) registers. */ static void fetch_fpregs (struct regcache *regcache, struct proc *thread) {
/* * Note that this 'irq' is the real repesentative irq for GPIO * * To reduce the register access, use the valid group cache. * first check the valid groups. if failed, scan all groups fully. */ static void samsung_irq_gpio_handler(unsigned int irq, struct irq_desc *desc) { struct samsung_irq_gpio *gpio; int group, n, offset; int start, end, pend, mask, handled = 0, action = 0; struct irq_chip *chip = get_irq_chip(irq); gpio = get_irq_data(irq); start = gpio->start; end = gpio->nr_groups; /* primary controller ack'ing */ if (chip->ack) chip->ack(irq); /* Check the valid group first */ for (group = 0; group <= end; group++) { if (!test_bit(group, &gpio->valid_groups)) continue; offset = REG_OFFSET(group); /* 4 bytes offset */ pend = __raw_readl(gpio->base + PEND_OFFSET + offset); if (!pend) continue; mask = __raw_readl(gpio->base + MASK_OFFSET + offset); pend &= ~mask; if (!pend) continue; while (pend) { n = fls(pend) - 1; generic_handle_irq(IRQ_GPIO_GROUP(start + group) + n); pend &= ~BIT(n); ++action; } handled = 1; } if (handled) goto out; /* Okay we can't find a proper handler. Scan fully */ for (group = 0; group <= end; group++) { offset = REG_OFFSET(group); /* 4 bytes offset */ pend = __raw_readl(gpio->base + PEND_OFFSET + offset); if (!pend) continue; mask = __raw_readl(gpio->base + MASK_OFFSET + offset); pend &= ~mask; while (pend) { n = fls(pend) - 1; generic_handle_irq(IRQ_GPIO_GROUP(start + group) + n); pend &= ~BIT(n); ++action; } /* It found the valid group */ set_bit(group, &gpio->valid_groups); } out: if (!action) do_bad_IRQ(irq, desc); /* primary controller unmasking */ chip->unmask(irq); }
#include <tcf/framework/context.h> #include <tcf/framework/myalloc.h> #include <tcf/framework/trace.h> #include <tcf/services/symbols.h> #include <tcf/services/runctrl.h> #include <machine/a64/tcf/disassembler-a64.h> #include <machine/a64/tcf/stack-crawl-a64.h> #if ENABLE_ContextMux #include <tcf/framework/cpudefs-mdep-mux.h> #endif #include <tcf/cpudefs-mdep.h> #define REG_OFFSET(name) offsetof(REG_SET, name) RegisterDefinition regs_def[] = { { "r0", REG_OFFSET(gp.regs[0]), 8, 0, 0}, { "sp", REG_OFFSET(gp.sp), 8, 31, 31}, { "pc", REG_OFFSET(gp.pc), 8, 33, 33}, { NULL, 0, 0, 0, 0}, }; RegisterDefinition * regs_index = NULL; static unsigned regs_cnt = 0; static unsigned regs_max = 0; unsigned char BREAK_INST[] = { 0x00, 0x00, 0x20, 0xd4 }; static RegisterDefinition * pc_def = NULL; RegisterDefinition * get_PC_definition(Context * ctx) { if (!context_has_state(ctx)) return NULL;
static errval_t elf_allocate(void *state, genvaddr_t base, size_t size, uint32_t flags, void **retbase) { errval_t err; lvaddr_t vaddr; size_t used_size; struct spawninfo *si = state; // Increase size by space wasted on first page due to page-alignment size_t base_offset = BASE_PAGE_OFFSET(base); size += base_offset; base -= base_offset; // Page-align size = ROUND_UP(size, BASE_PAGE_SIZE); cslot_t vspace_slot = si->elfload_slot; // Step 1: Allocate the frames size_t sz = 0; for (lpaddr_t offset = 0; offset < size; offset += sz) { sz = 1UL << log2floor(size - offset); struct capref frame = { .cnode = si->segcn, .slot = si->elfload_slot++, }; err = frame_create(frame, sz, NULL); if (err_is_fail(err)) { return err_push(err, LIB_ERR_FRAME_CREATE); } } cslot_t spawn_vspace_slot = si->elfload_slot; cslot_t new_slot_count = si->elfload_slot - vspace_slot; // Step 2: create copies of the frame capabilities for child vspace for (int copy_idx = 0; copy_idx < new_slot_count; copy_idx++) { struct capref frame = { .cnode = si->segcn, .slot = vspace_slot + copy_idx, }; struct capref spawn_frame = { .cnode = si->segcn, .slot = si->elfload_slot++, }; err = cap_copy(spawn_frame, frame); if (err_is_fail(err)) { debug_printf("cap_copy failed for src_slot = %"PRIuCSLOT ", dest_slot = %"PRIuCSLOT"\n", frame.slot, spawn_frame.slot); return err_push(err, LIB_ERR_CAP_COPY); } } // Step 3: map into own vspace // Get virtual address range to hold the module void *vaddr_range; err = paging_alloc(get_current_paging_state(), &vaddr_range, size); if (err_is_fail(err)) { debug_printf("elf_allocate: paging_alloc failed\n"); return (err); } // map allocated physical memory in virutal memory of parent process vaddr = (lvaddr_t)vaddr_range; used_size = size; while (used_size > 0) { struct capref frame = { .cnode = si->segcn, .slot = vspace_slot++, }; // find out the size of the frame struct frame_identity id; err = invoke_frame_identify(frame, &id); assert(err_is_ok(err)); size_t slot_size = (1UL << id.bits); // map frame to provide physical memory backing err = paging_map_fixed_attr(get_current_paging_state(), vaddr, frame, slot_size, VREGION_FLAGS_READ_WRITE); if (err_is_fail(err)) { debug_printf("elf_allocate: paging_map_fixed_attr failed\n"); return err; } used_size -= slot_size; vaddr += slot_size; } // end while: // Step 3: map into new process struct paging_state *cp = si->vspace; // map allocated physical memory in virutal memory of child process vaddr = (lvaddr_t)base; used_size = size; while (used_size > 0) { struct capref frame = { .cnode = si->segcn, .slot = spawn_vspace_slot++, }; // find out the size of the frame struct frame_identity id; err = invoke_frame_identify(frame, &id); assert(err_is_ok(err)); size_t slot_size = (1UL << id.bits); // map frame to provide physical memory backing err = paging_map_fixed_attr(cp, vaddr, frame, slot_size, elf_to_vregion_flags(flags)); if (err_is_fail(err)) { debug_printf("elf_allocate: paging_map_fixed_attr failed\n"); return err; } used_size -= slot_size; vaddr += slot_size; } // end while: *retbase = (void*) vaddr_range + base_offset; return SYS_ERR_OK; } // end function: elf_allocate /** * \brief Load the elf image */ errval_t spawn_arch_load(struct spawninfo *si, lvaddr_t binary, size_t binary_size, genvaddr_t *entry, void** arch_info) { errval_t err; // Reset the elfloader_slot si->elfload_slot = 0; struct capref cnode_cap = { .cnode = si->rootcn, .slot = ROOTCN_SLOT_SEGCN, }; err = cnode_create_raw(cnode_cap, &si->segcn, DEFAULT_CNODE_SLOTS, NULL); if (err_is_fail(err)) { return err_push(err, SPAWN_ERR_CREATE_SEGCN); } // TLS is NYI si->tls_init_base = 0; si->tls_init_len = si->tls_total_len = 0; //debug_printf("spawn_arch_load: about to load elf %p\n", elf_allocate); // Load the binary err = elf_load(EM_HOST, elf_allocate, si, binary, binary_size, entry); if (err_is_fail(err)) { return err; } //debug_printf("hello here\n"); struct Elf32_Shdr* got_shdr = elf32_find_section_header_name(binary, binary_size, ".got"); if (got_shdr) { *arch_info = (void*)got_shdr->sh_addr; } else { return SPAWN_ERR_LOAD; } return SYS_ERR_OK; } void spawn_arch_set_registers(void *arch_load_info, dispatcher_handle_t handle, arch_registers_state_t *enabled_area, arch_registers_state_t *disabled_area) { assert(arch_load_info != NULL); uintptr_t got_base = (uintptr_t)arch_load_info; struct dispatcher_shared_arm* disp_arm = get_dispatcher_shared_arm(handle); disp_arm->got_base = got_base; enabled_area->regs[REG_OFFSET(PIC_REGISTER)] = got_base; enabled_area->named.cpsr = CPSR_F_MASK | ARM_MODE_USR; disabled_area->regs[REG_OFFSET(PIC_REGISTER)] = got_base; disabled_area->named.cpsr = CPSR_F_MASK | ARM_MODE_USR; }
static struct sal_ret_values sal_emulator (long index, unsigned long in1, unsigned long in2, unsigned long in3, unsigned long in4, unsigned long in5, unsigned long in6, unsigned long in7) { long r9 = 0; long r10 = 0; long r11 = 0; long status; status = 0; if (index == SAL_FREQ_BASE) { if (in1 == SAL_FREQ_BASE_PLATFORM) r9 = 200000000; else if (in1 == SAL_FREQ_BASE_INTERVAL_TIMER) { r9 = 700000000; } else if (in1 == SAL_FREQ_BASE_REALTIME_CLOCK) r9 = 1; else status = -1; } else if (index == SAL_SET_VECTORS) { ; } else if (index == SAL_GET_STATE_INFO) { ; } else if (index == SAL_GET_STATE_INFO_SIZE) { ; } else if (index == SAL_CLEAR_STATE_INFO) { ; } else if (index == SAL_MC_RENDEZ) { ; } else if (index == SAL_MC_SET_PARAMS) { ; } else if (index == SAL_CACHE_FLUSH) { ; } else if (index == SAL_CACHE_INIT) { ; #ifdef CONFIG_PCI } else if (index == SAL_PCI_CONFIG_READ) { outl(BUILD_CMD(in1), 0xCF8); if (in2 == 1) r9 = inb(0xCFC + ((REG_OFFSET(in1) & 3))); else if (in2 == 2) r9 = inw(0xCFC + ((REG_OFFSET(in1) & 2))); else r9 = inl(0xCFC); status = PCIBIOS_SUCCESSFUL; } else if (index == SAL_PCI_CONFIG_WRITE) { /* * in1 contains the PCI configuration address, in2 the * size of the write, and in3 the actual value to be * written out. */ outl(BUILD_CMD(in1), 0xCF8); if (in2 == 1) outb(in3, 0xCFC + ((REG_OFFSET(in1) & 3))); else if (in2 == 2) outw(in3, 0xCFC + ((REG_OFFSET(in1) & 2))); else outl(in3, 0xCFC); status = PCIBIOS_SUCCESSFUL; #endif } else if (index == SAL_UPDATE_PAL) { ; } else { status = -1; } return ((struct sal_ret_values) {status, r9, r10, r11});
static void print_rtx (rtx in_rtx) { int i = 0; int j; const char *format_ptr; int is_insn; if (sawclose) { if (flag_simple) fputc (' ', outfile); else fprintf (outfile, "\n%s%*s", print_rtx_head, indent * 2, ""); sawclose = 0; } if (in_rtx == 0) { fputs ("(nil)", outfile); sawclose = 1; return; } else if (GET_CODE (in_rtx) > NUM_RTX_CODE) { fprintf (outfile, "(??? bad code %d\n)", GET_CODE (in_rtx)); sawclose = 1; return; } is_insn = INSN_P (in_rtx); /* When printing in VCG format we write INSNs, NOTE, LABEL, and BARRIER in separate nodes and therefore have to handle them special here. */ if (dump_for_graph && (is_insn || NOTE_P (in_rtx) || LABEL_P (in_rtx) || BARRIER_P (in_rtx))) { i = 3; indent = 0; } else { /* Print name of expression code. */ if (flag_simple && GET_CODE (in_rtx) == CONST_INT) fputc ('(', outfile); else fprintf (outfile, "(%s", GET_RTX_NAME (GET_CODE (in_rtx))); if (! flag_simple) { if (RTX_FLAG (in_rtx, in_struct)) fputs ("/s", outfile); if (RTX_FLAG (in_rtx, volatil)) fputs ("/v", outfile); if (RTX_FLAG (in_rtx, unchanging)) fputs ("/u", outfile); if (RTX_FLAG (in_rtx, frame_related)) fputs ("/f", outfile); if (RTX_FLAG (in_rtx, jump)) fputs ("/j", outfile); if (RTX_FLAG (in_rtx, call)) fputs ("/c", outfile); if (RTX_FLAG (in_rtx, return_val)) fputs ("/i", outfile); /* Print REG_NOTE names for EXPR_LIST and INSN_LIST. */ if (GET_CODE (in_rtx) == EXPR_LIST || GET_CODE (in_rtx) == INSN_LIST) fprintf (outfile, ":%s", GET_REG_NOTE_NAME (GET_MODE (in_rtx))); /* For other rtl, print the mode if it's not VOID. */ else if (GET_MODE (in_rtx) != VOIDmode) fprintf (outfile, ":%s", GET_MODE_NAME (GET_MODE (in_rtx))); } } #ifndef GENERATOR_FILE if (GET_CODE (in_rtx) == CONST_DOUBLE && FLOAT_MODE_P (GET_MODE (in_rtx))) i = 5; #endif /* Get the format string and skip the first elements if we have handled them already. */ format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx)) + i; for (; i < GET_RTX_LENGTH (GET_CODE (in_rtx)); i++) switch (*format_ptr++) { const char *str; case 'T': str = XTMPL (in_rtx, i); goto string; case 'S': case 's': str = XSTR (in_rtx, i); string: if (str == 0) fputs (dump_for_graph ? " \\\"\\\"" : " \"\"", outfile); else { if (dump_for_graph) fprintf (outfile, " (\\\"%s\\\")", str); else fprintf (outfile, " (\"%s\")", str); } sawclose = 1; break; /* 0 indicates a field for internal use that should not be printed. An exception is the third field of a NOTE, where it indicates that the field has several different valid contents. */ case '0': if (i == 1 && REG_P (in_rtx)) { if (REGNO (in_rtx) != ORIGINAL_REGNO (in_rtx)) fprintf (outfile, " [%d]", ORIGINAL_REGNO (in_rtx)); } #ifndef GENERATOR_FILE else if (i == 1 && GET_CODE (in_rtx) == SYMBOL_REF) { int flags = SYMBOL_REF_FLAGS (in_rtx); if (flags) fprintf (outfile, " [flags 0x%x]", flags); } else if (i == 2 && GET_CODE (in_rtx) == SYMBOL_REF) { tree decl = SYMBOL_REF_DECL (in_rtx); if (decl) print_node_brief (outfile, "", decl, 0); } #endif else if (i == 4 && NOTE_P (in_rtx)) { switch (NOTE_LINE_NUMBER (in_rtx)) { case NOTE_INSN_EH_REGION_BEG: case NOTE_INSN_EH_REGION_END: if (flag_dump_unnumbered) fprintf (outfile, " #"); else fprintf (outfile, " %d", NOTE_EH_HANDLER (in_rtx)); sawclose = 1; break; case NOTE_INSN_BLOCK_BEG: case NOTE_INSN_BLOCK_END: #ifndef GENERATOR_FILE dump_addr (outfile, " ", NOTE_BLOCK (in_rtx)); #endif sawclose = 1; break; case NOTE_INSN_BASIC_BLOCK: { #ifndef GENERATOR_FILE basic_block bb = NOTE_BASIC_BLOCK (in_rtx); if (bb != 0) fprintf (outfile, " [bb %d]", bb->index); #endif break; } case NOTE_INSN_EXPECTED_VALUE: indent += 2; if (!sawclose) fprintf (outfile, " "); print_rtx (NOTE_EXPECTED_VALUE (in_rtx)); indent -= 2; break; case NOTE_INSN_DELETED_LABEL: { const char *label = NOTE_DELETED_LABEL_NAME (in_rtx); if (label) fprintf (outfile, " (\"%s\")", label); else fprintf (outfile, " \"\""); } break; case NOTE_INSN_SWITCH_TEXT_SECTIONS: { #ifndef GENERATOR_FILE basic_block bb = NOTE_BASIC_BLOCK (in_rtx); if (bb != 0) fprintf (outfile, " [bb %d]", bb->index); #endif break; } case NOTE_INSN_VAR_LOCATION: #ifndef GENERATOR_FILE fprintf (outfile, " ("); print_mem_expr (outfile, NOTE_VAR_LOCATION_DECL (in_rtx)); fprintf (outfile, " "); print_rtx (NOTE_VAR_LOCATION_LOC (in_rtx)); fprintf (outfile, ")"); #endif break; default: { const char * const str = X0STR (in_rtx, i); if (NOTE_LINE_NUMBER (in_rtx) < 0) ; else if (str == 0) fputs (dump_for_graph ? " \\\"\\\"" : " \"\"", outfile); else { if (dump_for_graph) fprintf (outfile, " (\\\"%s\\\")", str); else fprintf (outfile, " (\"%s\")", str); } break; } } } break; case 'e': do_e: indent += 2; if (!sawclose) fprintf (outfile, " "); print_rtx (XEXP (in_rtx, i)); indent -= 2; break; case 'E': case 'V': indent += 2; if (sawclose) { fprintf (outfile, "\n%s%*s", print_rtx_head, indent * 2, ""); sawclose = 0; } fputs (" [", outfile); if (NULL != XVEC (in_rtx, i)) { indent += 2; if (XVECLEN (in_rtx, i)) sawclose = 1; for (j = 0; j < XVECLEN (in_rtx, i); j++) print_rtx (XVECEXP (in_rtx, i, j)); indent -= 2; } if (sawclose) fprintf (outfile, "\n%s%*s", print_rtx_head, indent * 2, ""); fputs ("]", outfile); sawclose = 1; indent -= 2; break; case 'w': if (! flag_simple) fprintf (outfile, " "); fprintf (outfile, HOST_WIDE_INT_PRINT_DEC, XWINT (in_rtx, i)); if (! flag_simple) fprintf (outfile, " [" HOST_WIDE_INT_PRINT_HEX "]", XWINT (in_rtx, i)); break; case 'i': if (i == 4 && INSN_P (in_rtx)) { #ifndef GENERATOR_FILE /* Pretty-print insn locators. Ignore scoping as it is mostly redundant with line number information and do not print anything when there is no location information available. */ if (INSN_LOCATOR (in_rtx) && insn_file (in_rtx)) fprintf(outfile, " %s:%i", insn_file (in_rtx), insn_line (in_rtx)); #endif } else if (i == 6 && NOTE_P (in_rtx)) { /* This field is only used for NOTE_INSN_DELETED_LABEL, and other times often contains garbage from INSN->NOTE death. */ if (NOTE_LINE_NUMBER (in_rtx) == NOTE_INSN_DELETED_LABEL) fprintf (outfile, " %d", XINT (in_rtx, i)); } else { int value = XINT (in_rtx, i); const char *name; #ifndef GENERATOR_FILE if (REG_P (in_rtx) && value < FIRST_PSEUDO_REGISTER) fprintf (outfile, " %d %s", REGNO (in_rtx), reg_names[REGNO (in_rtx)]); else if (REG_P (in_rtx) && value <= LAST_VIRTUAL_REGISTER) { if (value == VIRTUAL_INCOMING_ARGS_REGNUM) fprintf (outfile, " %d virtual-incoming-args", value); else if (value == VIRTUAL_STACK_VARS_REGNUM) fprintf (outfile, " %d virtual-stack-vars", value); else if (value == VIRTUAL_STACK_DYNAMIC_REGNUM) fprintf (outfile, " %d virtual-stack-dynamic", value); else if (value == VIRTUAL_OUTGOING_ARGS_REGNUM) fprintf (outfile, " %d virtual-outgoing-args", value); else if (value == VIRTUAL_CFA_REGNUM) fprintf (outfile, " %d virtual-cfa", value); else fprintf (outfile, " %d virtual-reg-%d", value, value-FIRST_VIRTUAL_REGISTER); } else #endif if (flag_dump_unnumbered && (is_insn || NOTE_P (in_rtx))) fputc ('#', outfile); else fprintf (outfile, " %d", value); #ifndef GENERATOR_FILE if (REG_P (in_rtx) && REG_ATTRS (in_rtx)) { fputs (" [", outfile); if (ORIGINAL_REGNO (in_rtx) != REGNO (in_rtx)) fprintf (outfile, "orig:%i", ORIGINAL_REGNO (in_rtx)); if (REG_EXPR (in_rtx)) print_mem_expr (outfile, REG_EXPR (in_rtx)); if (REG_OFFSET (in_rtx)) fprintf (outfile, "+" HOST_WIDE_INT_PRINT_DEC, REG_OFFSET (in_rtx)); fputs (" ]", outfile); } #endif if (is_insn && &INSN_CODE (in_rtx) == &XINT (in_rtx, i) && XINT (in_rtx, i) >= 0 && (name = get_insn_name (XINT (in_rtx, i))) != NULL) fprintf (outfile, " {%s}", name); sawclose = 0; } break; /* Print NOTE_INSN names rather than integer codes. */ case 'n': if (XINT (in_rtx, i) >= (int) NOTE_INSN_BIAS && XINT (in_rtx, i) < (int) NOTE_INSN_MAX) fprintf (outfile, " %s", GET_NOTE_INSN_NAME (XINT (in_rtx, i))); else fprintf (outfile, " %d", XINT (in_rtx, i)); sawclose = 0; break; case 'u': if (XEXP (in_rtx, i) != NULL) { rtx sub = XEXP (in_rtx, i); enum rtx_code subc = GET_CODE (sub); if (GET_CODE (in_rtx) == LABEL_REF) { if (subc == NOTE && NOTE_LINE_NUMBER (sub) == NOTE_INSN_DELETED_LABEL) { if (flag_dump_unnumbered) fprintf (outfile, " [# deleted]"); else fprintf (outfile, " [%d deleted]", INSN_UID (sub)); sawclose = 0; break; } if (subc != CODE_LABEL) goto do_e; } if (flag_dump_unnumbered) fputs (" #", outfile); else fprintf (outfile, " %d", INSN_UID (sub)); } else fputs (" 0", outfile); sawclose = 0; break; case 'b': #ifndef GENERATOR_FILE if (XBITMAP (in_rtx, i) == NULL) fputs (" {null}", outfile); else bitmap_print (outfile, XBITMAP (in_rtx, i), " {", "}"); #endif sawclose = 0; break; case 't': #ifndef GENERATOR_FILE dump_addr (outfile, " ", XTREE (in_rtx, i)); #endif break; case '*': fputs (" Unknown", outfile); sawclose = 0; break; case 'B': #ifndef GENERATOR_FILE if (XBBDEF (in_rtx, i)) fprintf (outfile, " %i", XBBDEF (in_rtx, i)->index); #endif break; default: gcc_unreachable (); } switch (GET_CODE (in_rtx)) { #ifndef GENERATOR_FILE case MEM: fprintf (outfile, " [" HOST_WIDE_INT_PRINT_DEC, MEM_ALIAS_SET (in_rtx)); if (MEM_EXPR (in_rtx)) print_mem_expr (outfile, MEM_EXPR (in_rtx)); if (MEM_OFFSET (in_rtx)) fprintf (outfile, "+" HOST_WIDE_INT_PRINT_DEC, INTVAL (MEM_OFFSET (in_rtx))); if (MEM_SIZE (in_rtx)) fprintf (outfile, " S" HOST_WIDE_INT_PRINT_DEC, INTVAL (MEM_SIZE (in_rtx))); if (MEM_ALIGN (in_rtx) != 1) fprintf (outfile, " A%u", MEM_ALIGN (in_rtx)); fputc (']', outfile); break; case CONST_DOUBLE: if (FLOAT_MODE_P (GET_MODE (in_rtx))) { char s[60]; real_to_decimal (s, CONST_DOUBLE_REAL_VALUE (in_rtx), sizeof (s), 0, 1); fprintf (outfile, " %s", s); real_to_hexadecimal (s, CONST_DOUBLE_REAL_VALUE (in_rtx), sizeof (s), 0, 1); fprintf (outfile, " [%s]", s); } break; #endif case CODE_LABEL: fprintf (outfile, " [%d uses]", LABEL_NUSES (in_rtx)); switch (LABEL_KIND (in_rtx)) { case LABEL_NORMAL: break; case LABEL_STATIC_ENTRY: fputs (" [entry]", outfile); break; case LABEL_GLOBAL_ENTRY: fputs (" [global entry]", outfile); break; case LABEL_WEAK_ENTRY: fputs (" [weak entry]", outfile); break; default: gcc_unreachable (); } break; default: break; } if (dump_for_graph && (is_insn || NOTE_P (in_rtx) || LABEL_P (in_rtx) || BARRIER_P (in_rtx))) sawclose = 0; else { fputc (')', outfile); sawclose = 1; } }
/* In older BSD versions we cannot get at some of the segment registers. FreeBSD for example didn't support the %fs and %gs registers until the 3.0 release. We have autoconf checks for their presence, and deal gracefully with their absence. */ /* Offset in `struct reg' where MEMBER is stored. */ #define REG_OFFSET(member) offsetof (struct reg, member) /* At i386bsd_reg_offset[REGNUM] you'll find the offset in `struct reg' where the GDB register REGNUM is stored. Unsupported registers are marked with `-1'. */ static int i386bsd_r_reg_offset[] = { REG_OFFSET (r_eax), REG_OFFSET (r_ecx), REG_OFFSET (r_edx), REG_OFFSET (r_ebx), REG_OFFSET (r_esp), REG_OFFSET (r_ebp), REG_OFFSET (r_esi), REG_OFFSET (r_edi), REG_OFFSET (r_eip), REG_OFFSET (r_eflags), REG_OFFSET (r_cs), REG_OFFSET (r_ss), REG_OFFSET (r_ds), REG_OFFSET (r_es), #ifdef HAVE_STRUCT_REG_R_FS REG_OFFSET (r_fs),
#if 1 #define REG_OFFSET(reg) (int)(&((struct mips_thread_state *)0)->reg) #define CREG_OFFSET(reg) (int)(&((struct mips_float_state *)0)->reg) #define EREG_OFFSET(reg) (int)(&((struct mips_exc_state *)0)->reg) /* at reg_offset[i] is the offset to the mips_thread_state * location where the gdb registers[i] is stored. * * -1 means mach does not save it anywhere. */ static int reg_offset[] = { /* zero at v0 v1 */ -1, REG_OFFSET (r1), REG_OFFSET (r2), REG_OFFSET (r3), /* a0 a1 a2 a3 */ REG_OFFSET (r4), REG_OFFSET (r5), REG_OFFSET (r6), REG_OFFSET (r7), /* t0 t1 t2 t3 */ REG_OFFSET (r8), REG_OFFSET (r9), REG_OFFSET (r10), REG_OFFSET (r11), /* t4 t5 t6 t7 */ REG_OFFSET (r12), REG_OFFSET (r13), REG_OFFSET (r14), REG_OFFSET (r15), /* s0 s1 s2 s3 */ REG_OFFSET (r16), REG_OFFSET (r17), REG_OFFSET (r18), REG_OFFSET (r19), /* s4 s5 s6 s7 */ REG_OFFSET (r20), REG_OFFSET (r21), REG_OFFSET (r22), REG_OFFSET (r23),