<commit_before>/*
 *  jemul8 - JavaScript x86 Emulator
 *  Copyright (c) 2012 http://ovms.co. All Rights Reserved.
 *
 * MODULE: Segment Register class support
 *
 * ====
 *
 * Copyright 2013 jemul8.com (http://github.com/asmblah/jemul8)
 * Released under the MIT license
 * http://jemul8.com/MIT-LICENSE.txt
 */

/*jslint bitwise: true, plusplus: true */
/*global define, require */

define([
    "../../util",
    "../register",
    "./selector",
    "./descriptor"
], function (
    util,
    Register,
    Selector,
    Descriptor
) {
    "use strict";

    // Segment Register (eg. CS, DS, ES, FS, GS) class constructor
    function SegRegister(name, size) {
        util.assert(this && (this instanceof SegRegister)
            , "SegRegister constructor :: error - not called properly"
        );

        Register.call(this, name, size);

        this.mask = util.generateMask(size);

        // Visible part of segment selector
        this.selector = new Selector();

        // Hidden "cache" for segment descriptors, populated
        //  when segment register's value is updated
        this.cache = new Descriptor();

        // Memory accessor (from MMU)
        //this.accessor = new Accessor();
    }
    util.inherit(SegRegister, Register); // Inheritance
    util.extend(SegRegister.prototype, {
        // Read a data quantum from this segment by virtual address/offset
        readSegment: function (addrVirtual, size) {
            //return this.accessor.read(addrVirtual, size);

            var machine = this.cpu.machine;
            var cpu = machine.cpu;
            var descriptor = this.cache;
            // Translate virtual address to linear by segmentation
            var addrLinear = descriptor.base + addrVirtual;
            var cpl = cpu.getCPL();

            if (addrVirtual > descriptor.limitScaled) {
                debugger;

                util.problem("SegRegister.readSegment() :: Segment limit violation");
                cpu.exception(this.getExceptionVector(), 0);
            }

            return machine.mem.readLinear(addrLinear, size, cpl);
        }, readSegmentBlock: function (addrVirtual, buffer, size) {
            //return this.accessor.read(addrVirtual, size);

            var machine = this.cpu.machine;
            var cpu = machine.cpu;
            var descriptor = this.cache;
            // Translate virtual address to linear by segmentation
            var addrLinear = descriptor.base + addrVirtual;
            var cpl = cpu.getCPL();

            if (addrVirtual > descriptor.limitScaled) {
                debugger;

                util.problem("SegRegister.readSegment() :: Segment limit violation");
                cpu.exception(this.getExceptionVector(), 0);
            }

            machine.mem.readLinearBlock(addrLinear, buffer, size, cpl);
        // Write data quantum to this segment by virtual address/offset
        }, writeSegment: function (addrVirtual, val, size) {
            //this.accessor.write(addrVirtual, val, size);

            var machine = this.cpu.machine;
            var cpu = machine.cpu;
            var descriptor = this.cache;
            // Translate virtual address to linear by segmentation
            var addrLinear = descriptor.base + addrVirtual;
            var cpl = cpu.getCPL();

            if (addrVirtual > descriptor.limitScaled) {
                util.problem("SegRegister.writeSegment() :: Segment limit violation");
                cpu.exception(this.getExceptionVector(), 0);
            }

            return machine.mem.writeLinear(addrLinear, val, size, cpl);
        // Translates a Virtual address to a Linear one by segmentation
        //  (NB: Not used in .read/writeSegment() as no handling is performed
        //  for memory protection etc.)
        }, virtualToLinear: function (addrVirtual) {
            return this.cache.base + addrVirtual;
        // Sets the Segment register back to its startup state
        }, reset: function () {
            var cache = this.cache;

            cache.accessType = util.ACCESS_VALID_CACHE
                | util.ACCESS_ROK
                | util.ACCESS_WOK;
            cache.present = true;
            cache.dpl = 0;
            cache.segment = 1; // Data/code segment
            cache.type = util.DESC_DATA_READ_WRITE_ACCESSED;

            cache.base = 0;
            // No scaling applied (x1) as byte-granular
            cache.limitScaled = 0xFFFF;
            cache.available = 0;
            cache.use4KPages = false;
            cache.default32BitSize = false;

            if (this === this.cpu.CS) {
                cache.base = 0xFFFF0000;
            }

            // Clear raw value too
            this.value = 0;
        // Loads a null selector into the segreg
        }, loadNullSelector: function (val) {
            util.assert((val & 0xFFFC) == 0
                , "SegRegister.loadNullSelector() :: Invalid value"
            );

            var selector = this.selector, cache = this.cache;

            selector.index = 0;
            selector.table = 0;
            selector.rpl = Selector.parse(val).rpl;

            cache.accessType = util.ACCESS_INVALID; // Invalidate null selector
            cache.present = false;
            cache.dpl = 0;
            cache.segment = true; // Code/data segment
            cache.type = 0;

            cache.base = 0;
            cache.limitScaled = 0;
            cache.use4KPages = false;
            cache.default32BitSize = false;
            cache.available = 0;
        // Segment Registers need special handling when set,
        //  eg. parsing selector & mapping
        }, set: function (val) {
            var machine = this.cpu.machine;
            var cpu = machine.cpu;
            var mem = machine.mem;
            var selector;
            var rawDescriptor;
            var descriptor;
            var cpl;

            // Mask out bits of value outside Register's bit-width
            val &= this.mask;

            // This is still a register: store its value
            this.value = val;

            // When (C)ode (S)egment is changed, eg. for a [far jmp],
            //  Instruction cache needs to be flushed
            if (this === cpu.CS) {
                cpu.flushInstructionCaches();
            }

            // Protected mode
            if (cpu.PE.get() && !cpu.VM.get()) {
                // Find out the Current Privilege Level
                //  for enforcing memory protection
                cpl = cpu.getCPL();
                debugger;
                // Loading Segment Selector is special
                if (this === cpu.SS) {
                    // Parse raw selector into components
                    selector = Selector.parse(val);

                    // Null selector
                    if ((val & 0xFFFC) === 0) {
                        util.problem("SS.set() :: Loading null selector");
                        cpu.exception(util.GP_EXCEPTION, val & 0xFFFC);
                    }

                    // Fetch raw descriptor as specified by selector
                    rawDescriptor = cpu.fetchRawDescriptor(selector, util.GP_EXCEPTION);

                    /* selector's RPL must = CPL, else #GP(selector) */
                    if (selector.rpl != cpl) {
                        util.problem("SS.set() :: RPL != CPL");
                        cpu.exception(util.GP_EXCEPTION, val & 0xFFFC);
                    }<commit_msg>Removed some legacy debugging code<commit_after>/*
 *  jemul8 - JavaScript x86 Emulator
 *  Copyright (c) 2012 http://ovms.co. All Rights Reserved.
 *
 * MODULE: Segment Register class support
 *
 * ====
 *
 * Copyright 2013 jemul8.com (http://github.com/asmblah/jemul8)
 * Released under the MIT license
 * http://jemul8.com/MIT-LICENSE.txt
 */

/*jslint bitwise: true, plusplus: true */
/*global define, require */

define([
    "../../util",
    "../register",
    "./selector",
    "./descriptor"
], function (
    util,
    Register,
    Selector,
    Descriptor
) {
    "use strict";

    // Segment Register (eg. CS, DS, ES, FS, GS) class constructor
    function SegRegister(name, size) {
        util.assert(this && (this instanceof SegRegister)
            , "SegRegister constructor :: error - not called properly"
        );

        Register.call(this, name, size);

        this.mask = util.generateMask(size);

        // Visible part of segment selector
        this.selector = new Selector();

        // Hidden "cache" for segment descriptors, populated
        //  when segment register's value is updated
        this.cache = new Descriptor();

        // Memory accessor (from MMU)
        //this.accessor = new Accessor();
    }
    util.inherit(SegRegister, Register); // Inheritance
    util.extend(SegRegister.prototype, {
        // Read a data quantum from this segment by virtual address/offset
        readSegment: function (addrVirtual, size) {
            //return this.accessor.read(addrVirtual, size);

            var machine = this.cpu.machine;
            var cpu = machine.cpu;
            var descriptor = this.cache;
            // Translate virtual address to linear by segmentation
            var addrLinear = descriptor.base + addrVirtual;
            var cpl = cpu.getCPL();

            if (addrVirtual > descriptor.limitScaled) {
                debugger;

                util.problem("SegRegister.readSegment() :: Segment limit violation");
                cpu.exception(this.getExceptionVector(), 0);
            }

            return machine.mem.readLinear(addrLinear, size, cpl);
        }, readSegmentBlock: function (addrVirtual, buffer, size) {
            //return this.accessor.read(addrVirtual, size);

            var machine = this.cpu.machine;
            var cpu = machine.cpu;
            var descriptor = this.cache;
            // Translate virtual address to linear by segmentation
            var addrLinear = descriptor.base + addrVirtual;
            var cpl = cpu.getCPL();

            if (addrVirtual > descriptor.limitScaled) {
                debugger;

                util.problem("SegRegister.readSegment() :: Segment limit violation");
                cpu.exception(this.getExceptionVector(), 0);
            }

            machine.mem.readLinearBlock(addrLinear, buffer, size, cpl);
        // Write data quantum to this segment by virtual address/offset
        }, writeSegment: function (addrVirtual, val, size) {
            //this.accessor.write(addrVirtual, val, size);

            var machine = this.cpu.machine;
            var cpu = machine.cpu;
            var descriptor = this.cache;
            // Translate virtual address to linear by segmentation
            var addrLinear = descriptor.base + addrVirtual;
            var cpl = cpu.getCPL();

            if (addrVirtual > descriptor.limitScaled) {
                util.problem("SegRegister.writeSegment() :: Segment limit violation");
                cpu.exception(this.getExceptionVector(), 0);
            }

            return machine.mem.writeLinear(addrLinear, val, size, cpl);
        // Translates a Virtual address to a Linear one by segmentation
        //  (NB: Not used in .read/writeSegment() as no handling is performed
        //  for memory protection etc.)
        }, virtualToLinear: function (addrVirtual) {
            return this.cache.base + addrVirtual;
        // Sets the Segment register back to its startup state
        }, reset: function () {
            var cache = this.cache;

            cache.accessType = util.ACCESS_VALID_CACHE
                | util.ACCESS_ROK
                | util.ACCESS_WOK;
            cache.present = true;
            cache.dpl = 0;
            cache.segment = 1; // Data/code segment
            cache.type = util.DESC_DATA_READ_WRITE_ACCESSED;

            cache.base = 0;
            // No scaling applied (x1) as byte-granular
            cache.limitScaled = 0xFFFF;
            cache.available = 0;
            cache.use4KPages = false;
            cache.default32BitSize = false;

            if (this === this.cpu.CS) {
                cache.base = 0xFFFF0000;
            }

            // Clear raw value too
            this.value = 0;
        // Loads a null selector into the segreg
        }, loadNullSelector: function (val) {
            util.assert((val & 0xFFFC) == 0
                , "SegRegister.loadNullSelector() :: Invalid value"
            );

            var selector = this.selector, cache = this.cache;

            selector.index = 0;
            selector.table = 0;
            selector.rpl = Selector.parse(val).rpl;

            cache.accessType = util.ACCESS_INVALID; // Invalidate null selector
            cache.present = false;
            cache.dpl = 0;
            cache.segment = true; // Code/data segment
            cache.type = 0;

            cache.base = 0;
            cache.limitScaled = 0;
            cache.use4KPages = false;
            cache.default32BitSize = false;
            cache.available = 0;
        // Segment Registers need special handling when set,
        //  eg. parsing selector & mapping
        }, set: function (val) {
            var machine = this.cpu.machine;
            var cpu = machine.cpu;
            var mem = machine.mem;
            var selector;
            var rawDescriptor;
            var descriptor;
            var cpl;

            // Mask out bits of value outside Register's bit-width
            val &= this.mask;

            // This is still a register: store its value
            this.value = val;

            // When (C)ode (S)egment is changed, eg. for a [far jmp],
            //  Instruction cache needs to be flushed
            if (this === cpu.CS) {
                cpu.flushInstructionCaches();
            }

            // Protected mode
            if (cpu.PE.get() && !cpu.VM.get()) {
                // Find out the Current Privilege Level
                //  for enforcing memory protection
                cpl = cpu.getCPL();

                // Loading Segment Selector is special
                if (this === cpu.SS) {
                    // Parse raw selector into components
                    selector = Selector.parse(val);

                    // Null selector
                    if ((val & 0xFFFC) === 0) {
                        util.problem("SS.set() :: Loading null selector");
                        cpu.exception(util.GP_EXCEPTION, val & 0xFFFC);
                    }

                    // Fetch raw descriptor as specified by selector
                    rawDescriptor = cpu.fetchRawDescriptor(selector, util.GP_EXCEPTION);

                    /* selector's RPL must = CPL, else #GP(selector) */
                    if (selector.rpl != cpl) {
                        util.problem("SS.set() :: RPL != CPL");
                        cpu.exception(util.GP_EXCEPTION, val & 0xFFFC);
                    }
{'fraction_non_alphanumeric': 0.10122246104245029, 'fraction_numerical': 0.006448146157979581, 'mean_word_length': 1.6025170424750919, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1528547', 'n_tokens_mistral': 3970, 'n_tokens_neox': 3709, 'n_words': 1085}