Annotation of qemu/hw/milkymist-pfpu.c, revision 1.1

1.1     ! root        1: /*
        !             2:  *  QEMU model of the Milkymist programmable FPU.
        !             3:  *
        !             4:  *  Copyright (c) 2010 Michael Walle <[email protected]>
        !             5:  *
        !             6:  * This library is free software; you can redistribute it and/or
        !             7:  * modify it under the terms of the GNU Lesser General Public
        !             8:  * License as published by the Free Software Foundation; either
        !             9:  * version 2 of the License, or (at your option) any later version.
        !            10:  *
        !            11:  * This library is distributed in the hope that it will be useful,
        !            12:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            13:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
        !            14:  * Lesser General Public License for more details.
        !            15:  *
        !            16:  * You should have received a copy of the GNU Lesser General Public
        !            17:  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
        !            18:  *
        !            19:  *
        !            20:  * Specification available at:
        !            21:  *   http://www.milkymist.org/socdoc/pfpu.pdf
        !            22:  *
        !            23:  */
        !            24: 
        !            25: #include "hw.h"
        !            26: #include "sysbus.h"
        !            27: #include "trace.h"
        !            28: #include "qemu-log.h"
        !            29: #include "qemu-error.h"
        !            30: #include <math.h>
        !            31: 
        !            32: /* #define TRACE_EXEC */
        !            33: 
        !            34: #ifdef TRACE_EXEC
        !            35: #    define D_EXEC(x) x
        !            36: #else
        !            37: #    define D_EXEC(x)
        !            38: #endif
        !            39: 
        !            40: enum {
        !            41:     R_CTL = 0,
        !            42:     R_MESHBASE,
        !            43:     R_HMESHLAST,
        !            44:     R_VMESHLAST,
        !            45:     R_CODEPAGE,
        !            46:     R_VERTICES,
        !            47:     R_COLLISIONS,
        !            48:     R_STRAYWRITES,
        !            49:     R_LASTDMA,
        !            50:     R_PC,
        !            51:     R_DREGBASE,
        !            52:     R_CODEBASE,
        !            53:     R_MAX
        !            54: };
        !            55: 
        !            56: enum {
        !            57:     CTL_START_BUSY = (1<<0),
        !            58: };
        !            59: 
        !            60: enum {
        !            61:     OP_NOP = 0,
        !            62:     OP_FADD,
        !            63:     OP_FSUB,
        !            64:     OP_FMUL,
        !            65:     OP_FABS,
        !            66:     OP_F2I,
        !            67:     OP_I2F,
        !            68:     OP_VECTOUT,
        !            69:     OP_SIN,
        !            70:     OP_COS,
        !            71:     OP_ABOVE,
        !            72:     OP_EQUAL,
        !            73:     OP_COPY,
        !            74:     OP_IF,
        !            75:     OP_TSIGN,
        !            76:     OP_QUAKE,
        !            77: };
        !            78: 
        !            79: enum {
        !            80:     GPR_X = 0,
        !            81:     GPR_Y = 1,
        !            82:     GPR_FLAGS = 2,
        !            83: };
        !            84: 
        !            85: enum {
        !            86:     LATENCY_FADD = 5,
        !            87:     LATENCY_FSUB = 5,
        !            88:     LATENCY_FMUL = 7,
        !            89:     LATENCY_FABS = 2,
        !            90:     LATENCY_F2I = 2,
        !            91:     LATENCY_I2F = 3,
        !            92:     LATENCY_VECTOUT = 0,
        !            93:     LATENCY_SIN = 4,
        !            94:     LATENCY_COS = 4,
        !            95:     LATENCY_ABOVE = 2,
        !            96:     LATENCY_EQUAL = 2,
        !            97:     LATENCY_COPY = 2,
        !            98:     LATENCY_IF = 2,
        !            99:     LATENCY_TSIGN = 2,
        !           100:     LATENCY_QUAKE = 2,
        !           101:     MAX_LATENCY = 7
        !           102: };
        !           103: 
        !           104: #define GPR_BEGIN       0x100
        !           105: #define GPR_END         0x17f
        !           106: #define MICROCODE_BEGIN 0x200
        !           107: #define MICROCODE_END   0x3ff
        !           108: #define MICROCODE_WORDS 2048
        !           109: 
        !           110: #define REINTERPRET_CAST(type, val) (*((type *)&(val)))
        !           111: 
        !           112: #ifdef TRACE_EXEC
        !           113: static const char *opcode_to_str[] = {
        !           114:     "NOP", "FADD", "FSUB", "FMUL", "FABS", "F2I", "I2F", "VECTOUT",
        !           115:     "SIN", "COS", "ABOVE", "EQUAL", "COPY", "IF", "TSIGN", "QUAKE",
        !           116: };
        !           117: #endif
        !           118: 
        !           119: struct MilkymistPFPUState {
        !           120:     SysBusDevice busdev;
        !           121:     CharDriverState *chr;
        !           122:     qemu_irq irq;
        !           123: 
        !           124:     uint32_t regs[R_MAX];
        !           125:     uint32_t gp_regs[128];
        !           126:     uint32_t microcode[MICROCODE_WORDS];
        !           127: 
        !           128:     int output_queue_pos;
        !           129:     uint32_t output_queue[MAX_LATENCY];
        !           130: };
        !           131: typedef struct MilkymistPFPUState MilkymistPFPUState;
        !           132: 
        !           133: static inline target_phys_addr_t
        !           134: get_dma_address(uint32_t base, uint32_t x, uint32_t y)
        !           135: {
        !           136:     return base + 8 * (128 * y + x);
        !           137: }
        !           138: 
        !           139: static inline void
        !           140: output_queue_insert(MilkymistPFPUState *s, uint32_t val, int pos)
        !           141: {
        !           142:     s->output_queue[(s->output_queue_pos + pos) % MAX_LATENCY] = val;
        !           143: }
        !           144: 
        !           145: static inline uint32_t
        !           146: output_queue_remove(MilkymistPFPUState *s)
        !           147: {
        !           148:     return s->output_queue[s->output_queue_pos];
        !           149: }
        !           150: 
        !           151: static inline void
        !           152: output_queue_advance(MilkymistPFPUState *s)
        !           153: {
        !           154:     s->output_queue[s->output_queue_pos] = 0;
        !           155:     s->output_queue_pos = (s->output_queue_pos + 1) % MAX_LATENCY;
        !           156: }
        !           157: 
        !           158: static int pfpu_decode_insn(MilkymistPFPUState *s)
        !           159: {
        !           160:     uint32_t pc = s->regs[R_PC];
        !           161:     uint32_t insn = s->microcode[pc];
        !           162:     uint32_t reg_a = (insn >> 18) & 0x7f;
        !           163:     uint32_t reg_b = (insn >> 11) & 0x7f;
        !           164:     uint32_t op = (insn >> 7) & 0xf;
        !           165:     uint32_t reg_d = insn & 0x7f;
        !           166:     uint32_t r = 0;
        !           167:     int latency = 0;
        !           168: 
        !           169:     switch (op) {
        !           170:     case OP_NOP:
        !           171:         break;
        !           172:     case OP_FADD:
        !           173:     {
        !           174:         float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]);
        !           175:         float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]);
        !           176:         float t = a + b;
        !           177:         r = REINTERPRET_CAST(uint32_t, t);
        !           178:         latency = LATENCY_FADD;
        !           179:         D_EXEC(qemu_log("ADD a=%f b=%f t=%f, r=%08x\n", a, b, t, r));
        !           180:     } break;
        !           181:     case OP_FSUB:
        !           182:     {
        !           183:         float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]);
        !           184:         float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]);
        !           185:         float t = a - b;
        !           186:         r = REINTERPRET_CAST(uint32_t, t);
        !           187:         latency = LATENCY_FSUB;
        !           188:         D_EXEC(qemu_log("SUB a=%f b=%f t=%f, r=%08x\n", a, b, t, r));
        !           189:     } break;
        !           190:     case OP_FMUL:
        !           191:     {
        !           192:         float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]);
        !           193:         float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]);
        !           194:         float t = a * b;
        !           195:         r = REINTERPRET_CAST(uint32_t, t);
        !           196:         latency = LATENCY_FMUL;
        !           197:         D_EXEC(qemu_log("MUL a=%f b=%f t=%f, r=%08x\n", a, b, t, r));
        !           198:     } break;
        !           199:     case OP_FABS:
        !           200:     {
        !           201:         float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]);
        !           202:         float t = fabsf(a);
        !           203:         r = REINTERPRET_CAST(uint32_t, t);
        !           204:         latency = LATENCY_FABS;
        !           205:         D_EXEC(qemu_log("ABS a=%f t=%f, r=%08x\n", a, t, r));
        !           206:     } break;
        !           207:     case OP_F2I:
        !           208:     {
        !           209:         float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]);
        !           210:         int32_t t = a;
        !           211:         r = REINTERPRET_CAST(uint32_t, t);
        !           212:         latency = LATENCY_F2I;
        !           213:         D_EXEC(qemu_log("F2I a=%f t=%d, r=%08x\n", a, t, r));
        !           214:     } break;
        !           215:     case OP_I2F:
        !           216:     {
        !           217:         int32_t a = REINTERPRET_CAST(int32_t, s->gp_regs[reg_a]);
        !           218:         float t = a;
        !           219:         r = REINTERPRET_CAST(uint32_t, t);
        !           220:         latency = LATENCY_I2F;
        !           221:         D_EXEC(qemu_log("I2F a=%08x t=%f, r=%08x\n", a, t, r));
        !           222:     } break;
        !           223:     case OP_VECTOUT:
        !           224:     {
        !           225:         uint32_t a = cpu_to_be32(s->gp_regs[reg_a]);
        !           226:         uint32_t b = cpu_to_be32(s->gp_regs[reg_b]);
        !           227:         target_phys_addr_t dma_ptr =
        !           228:             get_dma_address(s->regs[R_MESHBASE],
        !           229:                     s->gp_regs[GPR_X], s->gp_regs[GPR_Y]);
        !           230:         cpu_physical_memory_write(dma_ptr, (uint8_t *)&a, 4);
        !           231:         cpu_physical_memory_write(dma_ptr + 4, (uint8_t *)&b, 4);
        !           232:         s->regs[R_LASTDMA] = dma_ptr + 4;
        !           233:         D_EXEC(qemu_log("VECTOUT a=%08x b=%08x dma=%08x\n", a, b, dma_ptr));
        !           234:         trace_milkymist_pfpu_vectout(a, b, dma_ptr);
        !           235:     } break;
        !           236:     case OP_SIN:
        !           237:     {
        !           238:         int32_t a = REINTERPRET_CAST(int32_t, s->gp_regs[reg_a]);
        !           239:         float t = sinf(a * (1.0f / (M_PI * 4096.0f)));
        !           240:         r = REINTERPRET_CAST(uint32_t, t);
        !           241:         latency = LATENCY_SIN;
        !           242:         D_EXEC(qemu_log("SIN a=%d t=%f, r=%08x\n", a, t, r));
        !           243:     } break;
        !           244:     case OP_COS:
        !           245:     {
        !           246:         int32_t a = REINTERPRET_CAST(int32_t, s->gp_regs[reg_a]);
        !           247:         float t = cosf(a * (1.0f / (M_PI * 4096.0f)));
        !           248:         r = REINTERPRET_CAST(uint32_t, t);
        !           249:         latency = LATENCY_COS;
        !           250:         D_EXEC(qemu_log("COS a=%d t=%f, r=%08x\n", a, t, r));
        !           251:     } break;
        !           252:     case OP_ABOVE:
        !           253:     {
        !           254:         float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]);
        !           255:         float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]);
        !           256:         float t = (a > b) ? 1.0f : 0.0f;
        !           257:         r = REINTERPRET_CAST(uint32_t, t);
        !           258:         latency = LATENCY_ABOVE;
        !           259:         D_EXEC(qemu_log("ABOVE a=%f b=%f t=%f, r=%08x\n", a, b, t, r));
        !           260:     } break;
        !           261:     case OP_EQUAL:
        !           262:     {
        !           263:         float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]);
        !           264:         float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]);
        !           265:         float t = (a == b) ? 1.0f : 0.0f;
        !           266:         r = REINTERPRET_CAST(uint32_t, t);
        !           267:         latency = LATENCY_EQUAL;
        !           268:         D_EXEC(qemu_log("EQUAL a=%f b=%f t=%f, r=%08x\n", a, b, t, r));
        !           269:     } break;
        !           270:     case OP_COPY:
        !           271:     {
        !           272:         r = s->gp_regs[reg_a];
        !           273:         latency = LATENCY_COPY;
        !           274:         D_EXEC(qemu_log("COPY"));
        !           275:     } break;
        !           276:     case OP_IF:
        !           277:     {
        !           278:         float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]);
        !           279:         float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]);
        !           280:         uint32_t f = s->gp_regs[GPR_FLAGS];
        !           281:         float t = (f != 0) ? a : b;
        !           282:         r = REINTERPRET_CAST(uint32_t, t);
        !           283:         latency = LATENCY_IF;
        !           284:         D_EXEC(qemu_log("IF f=%u a=%f b=%f t=%f, r=%08x\n", f, a, b, t, r));
        !           285:     } break;
        !           286:     case OP_TSIGN:
        !           287:     {
        !           288:         float a = REINTERPRET_CAST(float, s->gp_regs[reg_a]);
        !           289:         float b = REINTERPRET_CAST(float, s->gp_regs[reg_b]);
        !           290:         float t = (b < 0) ? -a : a;
        !           291:         r = REINTERPRET_CAST(uint32_t, t);
        !           292:         latency = LATENCY_TSIGN;
        !           293:         D_EXEC(qemu_log("TSIGN a=%f b=%f t=%f, r=%08x\n", a, b, t, r));
        !           294:     } break;
        !           295:     case OP_QUAKE:
        !           296:     {
        !           297:         uint32_t a = s->gp_regs[reg_a];
        !           298:         r = 0x5f3759df - (a >> 1);
        !           299:         latency = LATENCY_QUAKE;
        !           300:         D_EXEC(qemu_log("QUAKE a=%d r=%08x\n", a, r));
        !           301:     } break;
        !           302: 
        !           303:     default:
        !           304:         error_report("milkymist_pfpu: unknown opcode %d", op);
        !           305:         break;
        !           306:     }
        !           307: 
        !           308:     if (!reg_d) {
        !           309:         D_EXEC(qemu_log("%04d %8s R%03d, R%03d <L=%d, E=%04d>\n",
        !           310:                     s->regs[R_PC], opcode_to_str[op], reg_a, reg_b, latency,
        !           311:                     s->regs[R_PC] + latency));
        !           312:     } else {
        !           313:         D_EXEC(qemu_log("%04d %8s R%03d, R%03d <L=%d, E=%04d> -> R%03d\n",
        !           314:                     s->regs[R_PC], opcode_to_str[op], reg_a, reg_b, latency,
        !           315:                     s->regs[R_PC] + latency, reg_d));
        !           316:     }
        !           317: 
        !           318:     if (op == OP_VECTOUT) {
        !           319:         return 0;
        !           320:     }
        !           321: 
        !           322:     /* store output for this cycle */
        !           323:     if (reg_d) {
        !           324:         uint32_t val = output_queue_remove(s);
        !           325:         D_EXEC(qemu_log("R%03d <- 0x%08x\n", reg_d, val));
        !           326:         s->gp_regs[reg_d] = val;
        !           327:     }
        !           328: 
        !           329:     output_queue_advance(s);
        !           330: 
        !           331:     /* store op output */
        !           332:     if (op != OP_NOP) {
        !           333:         output_queue_insert(s, r, latency-1);
        !           334:     }
        !           335: 
        !           336:     /* advance PC */
        !           337:     s->regs[R_PC]++;
        !           338: 
        !           339:     return 1;
        !           340: };
        !           341: 
        !           342: static void pfpu_start(MilkymistPFPUState *s)
        !           343: {
        !           344:     int x, y;
        !           345:     int i;
        !           346: 
        !           347:     for (y = 0; y <= s->regs[R_VMESHLAST]; y++) {
        !           348:         for (x = 0; x <= s->regs[R_HMESHLAST]; x++) {
        !           349:             D_EXEC(qemu_log("\nprocessing x=%d y=%d\n", x, y));
        !           350: 
        !           351:             /* set current position */
        !           352:             s->gp_regs[GPR_X] = x;
        !           353:             s->gp_regs[GPR_Y] = y;
        !           354: 
        !           355:             /* run microcode on this position */
        !           356:             i = 0;
        !           357:             while (pfpu_decode_insn(s)) {
        !           358:                 /* decode at most MICROCODE_WORDS instructions */
        !           359:                 if (i++ >= MICROCODE_WORDS) {
        !           360:                     error_report("milkymist_pfpu: too many instructions "
        !           361:                             "executed in microcode. No VECTOUT?");
        !           362:                     break;
        !           363:                 }
        !           364:             }
        !           365: 
        !           366:             /* reset pc for next run */
        !           367:             s->regs[R_PC] = 0;
        !           368:         }
        !           369:     }
        !           370: 
        !           371:     s->regs[R_VERTICES] = x * y;
        !           372: 
        !           373:     trace_milkymist_pfpu_pulse_irq();
        !           374:     qemu_irq_pulse(s->irq);
        !           375: }
        !           376: 
        !           377: static inline int get_microcode_address(MilkymistPFPUState *s, uint32_t addr)
        !           378: {
        !           379:     return (512 * s->regs[R_CODEPAGE]) + addr - MICROCODE_BEGIN;
        !           380: }
        !           381: 
        !           382: static uint32_t pfpu_read(void *opaque, target_phys_addr_t addr)
        !           383: {
        !           384:     MilkymistPFPUState *s = opaque;
        !           385:     uint32_t r = 0;
        !           386: 
        !           387:     addr >>= 2;
        !           388:     switch (addr) {
        !           389:     case R_CTL:
        !           390:     case R_MESHBASE:
        !           391:     case R_HMESHLAST:
        !           392:     case R_VMESHLAST:
        !           393:     case R_CODEPAGE:
        !           394:     case R_VERTICES:
        !           395:     case R_COLLISIONS:
        !           396:     case R_STRAYWRITES:
        !           397:     case R_LASTDMA:
        !           398:     case R_PC:
        !           399:     case R_DREGBASE:
        !           400:     case R_CODEBASE:
        !           401:         r = s->regs[addr];
        !           402:         break;
        !           403:     case GPR_BEGIN ... GPR_END:
        !           404:         r = s->gp_regs[addr - GPR_BEGIN];
        !           405:         break;
        !           406:     case MICROCODE_BEGIN ...  MICROCODE_END:
        !           407:         r = s->microcode[get_microcode_address(s, addr)];
        !           408:         break;
        !           409: 
        !           410:     default:
        !           411:         error_report("milkymist_pfpu: read access to unknown register 0x"
        !           412:                 TARGET_FMT_plx, addr << 2);
        !           413:         break;
        !           414:     }
        !           415: 
        !           416:     trace_milkymist_pfpu_memory_read(addr << 2, r);
        !           417: 
        !           418:     return r;
        !           419: }
        !           420: 
        !           421: static void
        !           422: pfpu_write(void *opaque, target_phys_addr_t addr, uint32_t value)
        !           423: {
        !           424:     MilkymistPFPUState *s = opaque;
        !           425: 
        !           426:     trace_milkymist_pfpu_memory_write(addr, value);
        !           427: 
        !           428:     addr >>= 2;
        !           429:     switch (addr) {
        !           430:     case R_CTL:
        !           431:         if (value & CTL_START_BUSY) {
        !           432:             pfpu_start(s);
        !           433:         }
        !           434:         break;
        !           435:     case R_MESHBASE:
        !           436:     case R_HMESHLAST:
        !           437:     case R_VMESHLAST:
        !           438:     case R_CODEPAGE:
        !           439:     case R_VERTICES:
        !           440:     case R_COLLISIONS:
        !           441:     case R_STRAYWRITES:
        !           442:     case R_LASTDMA:
        !           443:     case R_PC:
        !           444:     case R_DREGBASE:
        !           445:     case R_CODEBASE:
        !           446:         s->regs[addr] = value;
        !           447:         break;
        !           448:     case GPR_BEGIN ...  GPR_END:
        !           449:         s->gp_regs[addr - GPR_BEGIN] = value;
        !           450:         break;
        !           451:     case MICROCODE_BEGIN ...  MICROCODE_END:
        !           452:         s->microcode[get_microcode_address(s, addr)] = value;
        !           453:         break;
        !           454: 
        !           455:     default:
        !           456:         error_report("milkymist_pfpu: write access to unknown register 0x"
        !           457:                 TARGET_FMT_plx, addr << 2);
        !           458:         break;
        !           459:     }
        !           460: }
        !           461: 
        !           462: static CPUReadMemoryFunc * const pfpu_read_fn[] = {
        !           463:     NULL,
        !           464:     NULL,
        !           465:     &pfpu_read,
        !           466: };
        !           467: 
        !           468: static CPUWriteMemoryFunc * const pfpu_write_fn[] = {
        !           469:     NULL,
        !           470:     NULL,
        !           471:     &pfpu_write,
        !           472: };
        !           473: 
        !           474: static void milkymist_pfpu_reset(DeviceState *d)
        !           475: {
        !           476:     MilkymistPFPUState *s = container_of(d, MilkymistPFPUState, busdev.qdev);
        !           477:     int i;
        !           478: 
        !           479:     for (i = 0; i < R_MAX; i++) {
        !           480:         s->regs[i] = 0;
        !           481:     }
        !           482:     for (i = 0; i < 128; i++) {
        !           483:         s->gp_regs[i] = 0;
        !           484:     }
        !           485:     for (i = 0; i < MICROCODE_WORDS; i++) {
        !           486:         s->microcode[i] = 0;
        !           487:     }
        !           488:     s->output_queue_pos = 0;
        !           489:     for (i = 0; i < MAX_LATENCY; i++) {
        !           490:         s->output_queue[i] = 0;
        !           491:     }
        !           492: }
        !           493: 
        !           494: static int milkymist_pfpu_init(SysBusDevice *dev)
        !           495: {
        !           496:     MilkymistPFPUState *s = FROM_SYSBUS(typeof(*s), dev);
        !           497:     int pfpu_regs;
        !           498: 
        !           499:     sysbus_init_irq(dev, &s->irq);
        !           500: 
        !           501:     pfpu_regs = cpu_register_io_memory(pfpu_read_fn, pfpu_write_fn, s,
        !           502:             DEVICE_NATIVE_ENDIAN);
        !           503:     sysbus_init_mmio(dev, MICROCODE_END * 4, pfpu_regs);
        !           504: 
        !           505:     return 0;
        !           506: }
        !           507: 
        !           508: static const VMStateDescription vmstate_milkymist_pfpu = {
        !           509:     .name = "milkymist-pfpu",
        !           510:     .version_id = 1,
        !           511:     .minimum_version_id = 1,
        !           512:     .minimum_version_id_old = 1,
        !           513:     .fields      = (VMStateField[]) {
        !           514:         VMSTATE_UINT32_ARRAY(regs, MilkymistPFPUState, R_MAX),
        !           515:         VMSTATE_UINT32_ARRAY(gp_regs, MilkymistPFPUState, 128),
        !           516:         VMSTATE_UINT32_ARRAY(microcode, MilkymistPFPUState, MICROCODE_WORDS),
        !           517:         VMSTATE_INT32(output_queue_pos, MilkymistPFPUState),
        !           518:         VMSTATE_UINT32_ARRAY(output_queue, MilkymistPFPUState, MAX_LATENCY),
        !           519:         VMSTATE_END_OF_LIST()
        !           520:     }
        !           521: };
        !           522: 
        !           523: static SysBusDeviceInfo milkymist_pfpu_info = {
        !           524:     .init = milkymist_pfpu_init,
        !           525:     .qdev.name  = "milkymist-pfpu",
        !           526:     .qdev.size  = sizeof(MilkymistPFPUState),
        !           527:     .qdev.vmsd  = &vmstate_milkymist_pfpu,
        !           528:     .qdev.reset = milkymist_pfpu_reset,
        !           529: };
        !           530: 
        !           531: static void milkymist_pfpu_register(void)
        !           532: {
        !           533:     sysbus_register_withprop(&milkymist_pfpu_info);
        !           534: }
        !           535: 
        !           536: device_init(milkymist_pfpu_register)

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.